node-version-use 2.1.2 → 2.1.4

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.
@@ -0,0 +1,428 @@
1
+ /**
2
+ * Postinstall script for node-version-use
3
+ *
4
+ * Downloads the platform-specific binary and installs it to ~/.nvu/bin/
5
+ * This enables transparent Node version switching.
6
+ *
7
+ * Uses safe atomic download pattern:
8
+ * 1. Download to temp file
9
+ * 2. Extract to temp directory
10
+ * 3. Atomic rename to final location
11
+ */ "use strict";
12
+ Object.defineProperty(exports, "__esModule", {
13
+ value: true
14
+ });
15
+ var _child_process = require("child_process");
16
+ var _exitcompat = /*#__PURE__*/ _interop_require_default(require("exit-compat"));
17
+ var _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
18
+ var _mkdirpclassic = /*#__PURE__*/ _interop_require_default(require("mkdirp-classic"));
19
+ var _module = /*#__PURE__*/ _interop_require_default(require("module"));
20
+ var _os = /*#__PURE__*/ _interop_require_default(require("os"));
21
+ var _path = /*#__PURE__*/ _interop_require_default(require("path"));
22
+ var _url = /*#__PURE__*/ _interop_require_default(require("url"));
23
+ var _compatts = require("../compat.js");
24
+ function _interop_require_default(obj) {
25
+ return obj && obj.__esModule ? obj : {
26
+ default: obj
27
+ };
28
+ }
29
+ // CJS/ESM compatibility
30
+ var _require = typeof require === 'undefined' ? _module.default.createRequire(require("url").pathToFileURL(__filename).toString()) : require;
31
+ var __dirname = _path.default.dirname(typeof __filename !== 'undefined' ? __filename : _url.default.fileURLToPath(require("url").pathToFileURL(__filename).toString()));
32
+ // Configuration
33
+ var GITHUB_REPO = 'kmalakoff/node-version-use';
34
+ // Path is relative to dist/cjs/scripts/ at runtime
35
+ var BINARY_VERSION = _require(_path.default.join(__dirname, '..', '..', '..', 'package.json')).binaryVersion;
36
+ /**
37
+ * Get the platform-specific archive base name (without extension)
38
+ */ function getArchiveBaseName() {
39
+ var platform = _os.default.platform();
40
+ var arch = _os.default.arch();
41
+ var platformMap = {
42
+ darwin: 'darwin',
43
+ linux: 'linux',
44
+ win32: 'win32'
45
+ };
46
+ var archMap = {
47
+ x64: 'x64',
48
+ arm64: 'arm64',
49
+ amd64: 'x64'
50
+ };
51
+ var platformName = platformMap[platform];
52
+ var archName = archMap[arch];
53
+ if (!platformName || !archName) {
54
+ return null;
55
+ }
56
+ return "nvu-binary-".concat(platformName, "-").concat(archName);
57
+ }
58
+ /**
59
+ * Get the extracted binary name (includes .exe on Windows)
60
+ */ function getExtractedBinaryName(archiveBaseName) {
61
+ var ext = _os.default.platform() === 'win32' ? '.exe' : '';
62
+ return archiveBaseName + ext;
63
+ }
64
+ /**
65
+ * Get the download URL for the binary archive
66
+ */ function getDownloadUrl(archiveBaseName) {
67
+ var ext = _os.default.platform() === 'win32' ? '.zip' : '.tar.gz';
68
+ return "https://github.com/".concat(GITHUB_REPO, "/releases/download/binary-v").concat(BINARY_VERSION, "/").concat(archiveBaseName).concat(ext);
69
+ }
70
+ /**
71
+ * Copy file
72
+ */ function copyFileSync(src, dest) {
73
+ var content = _fs.default.readFileSync(src);
74
+ _fs.default.writeFileSync(dest, content);
75
+ }
76
+ /**
77
+ * Atomic rename with fallback to copy+delete for cross-device moves
78
+ */ function atomicRename(src, dest, callback) {
79
+ _fs.default.rename(src, dest, function(err) {
80
+ if (!err) {
81
+ callback(null);
82
+ return;
83
+ }
84
+ // Cross-device link error - fall back to copy + delete
85
+ if (err.code === 'EXDEV') {
86
+ try {
87
+ copyFileSync(src, dest);
88
+ _fs.default.unlinkSync(src);
89
+ callback(null);
90
+ } catch (copyErr) {
91
+ callback(copyErr);
92
+ }
93
+ return;
94
+ }
95
+ callback(err);
96
+ });
97
+ }
98
+ /**
99
+ * Remove directory recursively
100
+ */ function rmRecursive(dir) {
101
+ if (!_fs.default.existsSync(dir)) return;
102
+ var files = _fs.default.readdirSync(dir);
103
+ for(var i = 0; i < files.length; i++){
104
+ var filePath = _path.default.join(dir, files[i]);
105
+ var stat = _fs.default.statSync(filePath);
106
+ if (stat.isDirectory()) {
107
+ rmRecursive(filePath);
108
+ } else {
109
+ _fs.default.unlinkSync(filePath);
110
+ }
111
+ }
112
+ _fs.default.rmdirSync(dir);
113
+ }
114
+ /**
115
+ * Get temp directory
116
+ */ function getTmpDir() {
117
+ return typeof _os.default.tmpdir === 'function' ? _os.default.tmpdir() : process.env.TMPDIR || process.env.TMP || process.env.TEMP || '/tmp';
118
+ }
119
+ /**
120
+ * Download using curl (macOS, Linux, Windows 10+)
121
+ */ function downloadWithCurl(downloadUrl, destPath, callback) {
122
+ var curl = (0, _child_process.spawn)('curl', [
123
+ '-L',
124
+ '-f',
125
+ '-s',
126
+ '-o',
127
+ destPath,
128
+ downloadUrl
129
+ ]);
130
+ curl.on('close', function(code) {
131
+ if (code !== 0) {
132
+ // curl exit codes: 22 = HTTP error (4xx/5xx), 56 = receive error (often 404 with -f)
133
+ if (code === 22 || code === 56) {
134
+ callback(new Error('HTTP 404'));
135
+ } else {
136
+ callback(new Error("curl failed with exit code ".concat(code)));
137
+ }
138
+ return;
139
+ }
140
+ callback(null);
141
+ });
142
+ curl.on('error', function(err) {
143
+ callback(err);
144
+ });
145
+ }
146
+ /**
147
+ * Download using PowerShell (Windows 7+ fallback)
148
+ */ function downloadWithPowerShell(downloadUrl, destPath, callback) {
149
+ var psCommand = 'Invoke-WebRequest -Uri "'.concat(downloadUrl, '" -OutFile "').concat(destPath, '" -UseBasicParsing');
150
+ var ps = (0, _child_process.spawn)('powershell', [
151
+ '-NoProfile',
152
+ '-Command',
153
+ psCommand
154
+ ]);
155
+ ps.on('close', function(code) {
156
+ if (code !== 0) {
157
+ callback(new Error("PowerShell download failed with exit code ".concat(code)));
158
+ return;
159
+ }
160
+ callback(null);
161
+ });
162
+ ps.on('error', function(err) {
163
+ callback(err);
164
+ });
165
+ }
166
+ /**
167
+ * Download a file - tries curl first, falls back to PowerShell on Windows
168
+ * Node 0.8's OpenSSL doesn't support TLS 1.2+ required by GitHub
169
+ */ function downloadFile(downloadUrl, destPath, callback) {
170
+ downloadWithCurl(downloadUrl, destPath, function(err) {
171
+ var _err_message;
172
+ if (!err) {
173
+ callback(null);
174
+ return;
175
+ }
176
+ // If curl failed and we're on Windows, try PowerShell
177
+ if (_os.default.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) {
178
+ downloadWithPowerShell(downloadUrl, destPath, callback);
179
+ return;
180
+ }
181
+ callback(err);
182
+ });
183
+ }
184
+ /**
185
+ * Extract archive to a directory (callback-based)
186
+ */ function extractArchive(archivePath, destDir, callback) {
187
+ var platform = _os.default.platform();
188
+ if (platform === 'win32') {
189
+ // Windows: extract zip using PowerShell
190
+ var ps = (0, _child_process.spawn)('powershell', [
191
+ '-Command',
192
+ "Expand-Archive -Path '".concat(archivePath, "' -DestinationPath '").concat(destDir, "' -Force")
193
+ ]);
194
+ ps.on('close', function(code) {
195
+ if (code !== 0) {
196
+ callback(new Error('Failed to extract archive'));
197
+ return;
198
+ }
199
+ callback(null);
200
+ });
201
+ } else {
202
+ // Unix: extract tar.gz
203
+ var tar = (0, _child_process.spawn)('tar', [
204
+ '-xzf',
205
+ archivePath,
206
+ '-C',
207
+ destDir
208
+ ]);
209
+ tar.on('close', function(code) {
210
+ if (code !== 0) {
211
+ callback(new Error('Failed to extract archive'));
212
+ return;
213
+ }
214
+ callback(null);
215
+ });
216
+ }
217
+ }
218
+ /**
219
+ * Install binaries using atomic rename pattern
220
+ * 1. Extract to temp directory
221
+ * 2. Copy binary to temp files in destination directory
222
+ * 3. Atomic rename temp files to final names
223
+ */ function extractAndInstall(archivePath, destDir, binaryName, callback) {
224
+ var platform = _os.default.platform();
225
+ var isWindows = platform === 'win32';
226
+ var ext = isWindows ? '.exe' : '';
227
+ // Create temp extraction directory
228
+ var tempExtractDir = _path.default.join(getTmpDir(), "nvu-extract-".concat(Date.now()));
229
+ _mkdirpclassic.default.sync(tempExtractDir);
230
+ extractArchive(archivePath, tempExtractDir, function(extractErr) {
231
+ if (extractErr) {
232
+ rmRecursive(tempExtractDir);
233
+ callback(extractErr);
234
+ return;
235
+ }
236
+ var extractedPath = _path.default.join(tempExtractDir, binaryName);
237
+ if (!_fs.default.existsSync(extractedPath)) {
238
+ rmRecursive(tempExtractDir);
239
+ callback(new Error("Extracted binary not found: ".concat(binaryName)));
240
+ return;
241
+ }
242
+ // Binary names to install
243
+ var binaries = [
244
+ 'node',
245
+ 'npm',
246
+ 'npx',
247
+ 'corepack'
248
+ ];
249
+ var timestamp = Date.now();
250
+ var installError = null;
251
+ // Step 1: Copy extracted binary to temp files in destination directory
252
+ // This ensures the temp files are on the same filesystem for atomic rename
253
+ for(var i = 0; i < binaries.length; i++){
254
+ var name = binaries[i];
255
+ var tempDest = _path.default.join(destDir, "".concat(name, ".tmp-").concat(timestamp).concat(ext));
256
+ try {
257
+ // Copy to temp file in destination directory
258
+ copyFileSync(extractedPath, tempDest);
259
+ // Set permissions on Unix
260
+ if (!isWindows) {
261
+ _fs.default.chmodSync(tempDest, 493);
262
+ }
263
+ } catch (err) {
264
+ installError = err;
265
+ break;
266
+ }
267
+ }
268
+ if (installError) {
269
+ // Clean up any temp files we created
270
+ for(var j = 0; j < binaries.length; j++){
271
+ var tempPath = _path.default.join(destDir, "".concat(binaries[j], ".tmp-").concat(timestamp).concat(ext));
272
+ if (_fs.default.existsSync(tempPath)) {
273
+ try {
274
+ _fs.default.unlinkSync(tempPath);
275
+ } catch (_e) {
276
+ // ignore cleanup errors
277
+ }
278
+ }
279
+ }
280
+ rmRecursive(tempExtractDir);
281
+ callback(installError);
282
+ return;
283
+ }
284
+ // Step 2: Atomic rename temp files to final names
285
+ var renameError = null;
286
+ function doRename(index) {
287
+ if (index >= binaries.length) {
288
+ // All renames complete
289
+ rmRecursive(tempExtractDir);
290
+ callback(renameError);
291
+ return;
292
+ }
293
+ var name = binaries[index];
294
+ var tempDest = _path.default.join(destDir, "".concat(name, ".tmp-").concat(timestamp).concat(ext));
295
+ var finalDest = _path.default.join(destDir, "".concat(name).concat(ext));
296
+ // Remove existing file if present (for atomic replacement)
297
+ if (_fs.default.existsSync(finalDest)) {
298
+ try {
299
+ _fs.default.unlinkSync(finalDest);
300
+ } catch (_e) {
301
+ // ignore cleanup errors
302
+ }
303
+ }
304
+ atomicRename(tempDest, finalDest, function(err) {
305
+ if (err && !renameError) {
306
+ renameError = err;
307
+ }
308
+ doRename(index + 1);
309
+ });
310
+ }
311
+ doRename(0);
312
+ });
313
+ }
314
+ /**
315
+ * Print setup instructions
316
+ */ function printInstructions(installed) {
317
+ var homedirPath = (0, _compatts.homedir)();
318
+ var nvuBinPath = _path.default.join(homedirPath, '.nvu', 'bin');
319
+ var platform = _os.default.platform();
320
+ console.log('');
321
+ console.log('============================================================');
322
+ if (installed) {
323
+ console.log(' nvu binaries installed to ~/.nvu/bin/');
324
+ } else {
325
+ console.log(' nvu installed (binaries not yet available)');
326
+ }
327
+ console.log('============================================================');
328
+ console.log('');
329
+ console.log('To enable transparent Node version switching, add to your shell profile:');
330
+ console.log('');
331
+ if (platform === 'win32') {
332
+ console.log(' PowerShell (add to $PROFILE):');
333
+ console.log(' $env:PATH = "'.concat(nvuBinPath, ';$env:PATH"'));
334
+ console.log('');
335
+ console.log(' CMD (run as administrator):');
336
+ console.log(' setx PATH "'.concat(nvuBinPath, ';%PATH%"'));
337
+ } else {
338
+ console.log(' # For bash (~/.bashrc):');
339
+ console.log(' export PATH="$HOME/.nvu/bin:$PATH"');
340
+ console.log('');
341
+ console.log(' # For zsh (~/.zshrc):');
342
+ console.log(' export PATH="$HOME/.nvu/bin:$PATH"');
343
+ console.log('');
344
+ console.log(' # For fish (~/.config/fish/config.fish):');
345
+ console.log(' set -gx PATH $HOME/.nvu/bin $PATH');
346
+ }
347
+ console.log('');
348
+ console.log('Then restart your terminal or source your shell profile.');
349
+ console.log('');
350
+ console.log("Without this, 'nvu 18 npm test' still works - you just won't have");
351
+ console.log("transparent 'node' command override.");
352
+ console.log('============================================================');
353
+ }
354
+ /**
355
+ * Main installation function
356
+ */ function main() {
357
+ var archiveBaseName = getArchiveBaseName();
358
+ if (!archiveBaseName) {
359
+ console.log('postinstall: Unsupported platform/architecture for binary.');
360
+ console.log("Platform: ".concat(_os.default.platform(), ", Arch: ").concat(_os.default.arch()));
361
+ console.log('Binary not installed. You can still use nvu with explicit versions: nvu 18 npm test');
362
+ (0, _exitcompat.default)(0);
363
+ return;
364
+ }
365
+ var extractedBinaryName = getExtractedBinaryName(archiveBaseName);
366
+ var homedirPath = (0, _compatts.homedir)();
367
+ var nvuDir = _path.default.join(homedirPath, '.nvu');
368
+ var binDir = _path.default.join(nvuDir, 'bin');
369
+ // Create directories
370
+ _mkdirpclassic.default.sync(nvuDir);
371
+ _mkdirpclassic.default.sync(binDir);
372
+ var downloadUrl = getDownloadUrl(archiveBaseName);
373
+ var ext = _os.default.platform() === 'win32' ? '.zip' : '.tar.gz';
374
+ var tempPath = _path.default.join(getTmpDir(), "nvu-binary-".concat(Date.now()).concat(ext));
375
+ console.log("postinstall: Downloading binary for ".concat(_os.default.platform(), "-").concat(_os.default.arch(), "..."));
376
+ downloadFile(downloadUrl, tempPath, function(downloadErr) {
377
+ if (downloadErr) {
378
+ var _downloadErr_message;
379
+ // Clean up temp file if it exists
380
+ if (_fs.default.existsSync(tempPath)) {
381
+ try {
382
+ _fs.default.unlinkSync(tempPath);
383
+ } catch (_e) {
384
+ // ignore cleanup errors
385
+ }
386
+ }
387
+ if (((_downloadErr_message = downloadErr.message) === null || _downloadErr_message === void 0 ? void 0 : _downloadErr_message.indexOf('404')) >= 0) {
388
+ console.log('postinstall: Binaries not yet published to GitHub releases.');
389
+ console.log('');
390
+ console.log('To build and install binaries locally:');
391
+ console.log(' cd node_modules/node-version-use/binary');
392
+ console.log(' make install');
393
+ console.log('');
394
+ console.log('Or wait for the next release which will include pre-built binaries.');
395
+ } else {
396
+ console.log("postinstall warning: Failed to install binary: ".concat(downloadErr.message || downloadErr));
397
+ console.log('You can still use nvu with explicit versions: nvu 18 npm test');
398
+ console.log('To install binaries manually: cd node_modules/node-version-use/binary && make install');
399
+ }
400
+ printInstructions(false);
401
+ (0, _exitcompat.default)(0);
402
+ return;
403
+ }
404
+ console.log('postinstall: Extracting binary...');
405
+ extractAndInstall(tempPath, binDir, extractedBinaryName, function(extractErr) {
406
+ // Clean up temp file
407
+ if (_fs.default.existsSync(tempPath)) {
408
+ try {
409
+ _fs.default.unlinkSync(tempPath);
410
+ } catch (_e) {
411
+ // ignore cleanup errors
412
+ }
413
+ }
414
+ if (extractErr) {
415
+ console.log("postinstall warning: Failed to extract binary: ".concat(extractErr.message || extractErr));
416
+ console.log('You can still use nvu with explicit versions: nvu 18 npm test');
417
+ printInstructions(false);
418
+ (0, _exitcompat.default)(0);
419
+ return;
420
+ }
421
+ console.log('postinstall: Binary installed successfully!');
422
+ printInstructions(true);
423
+ (0, _exitcompat.default)(0);
424
+ });
425
+ });
426
+ }
427
+ main();
428
+ /* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node-version/node-version-use/src/scripts/postinstall.ts"],"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\nimport { spawn } from 'child_process';\nimport exit from 'exit-compat';\nimport fs from 'fs';\nimport mkdirp from 'mkdirp-classic';\nimport Module from 'module';\nimport os from 'os';\nimport path from 'path';\nimport url from 'url';\nimport { homedir } from '../compat.ts';\n\n// CJS/ESM compatibility\nconst _require = typeof require === 'undefined' ? Module.createRequire(import.meta.url) : require;\nconst __dirname = path.dirname(typeof __filename !== 'undefined' ? __filename : url.fileURLToPath(import.meta.url));\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":["_require","require","Module","createRequire","__dirname","path","dirname","__filename","url","fileURLToPath","GITHUB_REPO","BINARY_VERSION","join","binaryVersion","getArchiveBaseName","platform","os","arch","platformMap","darwin","linux","win32","archMap","x64","arm64","amd64","platformName","archName","getExtractedBinaryName","archiveBaseName","ext","getDownloadUrl","copyFileSync","src","dest","content","fs","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","spawn","on","Error","downloadWithPowerShell","psCommand","ps","downloadFile","message","indexOf","extractArchive","archivePath","destDir","tar","extractAndInstall","binaryName","isWindows","tempExtractDir","Date","now","mkdirp","sync","extractErr","extractedPath","binaries","timestamp","installError","name","tempDest","chmodSync","j","tempPath","_e","renameError","doRename","index","finalDest","printInstructions","installed","homedirPath","homedir","nvuBinPath","console","log","main","exit","extractedBinaryName","nvuDir","binDir","downloadErr"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  /**
2
- * nvu setup
2
+ * nvu setup [--shims]
3
3
  *
4
4
  * Install/reinstall nvu binaries to ~/.nvu/bin
5
- * This runs the same logic as the postinstall script.
5
+ * With --shims: create shims for existing global packages
6
6
  */
7
- export default function setupCmd(_args: string[]): void;
7
+ export default function setupCmd(args: string[]): void;
@@ -3,15 +3,16 @@ import exit from 'exit-compat';
3
3
  import fs from 'fs';
4
4
  import path from 'path';
5
5
  import url from 'url';
6
- import { mkdirpSync } from '../compat.js';
6
+ import { mkdirpSync, readdirWithTypes } from '../compat.js';
7
7
  import { storagePath } from '../constants.js';
8
+ import { findInstalledVersions } from '../lib/findInstalledVersions.js';
8
9
  var __dirname = path.dirname(typeof __filename !== 'undefined' ? __filename : url.fileURLToPath(import.meta.url));
9
10
  /**
10
- * nvu setup
11
+ * nvu setup [--shims]
11
12
  *
12
13
  * Install/reinstall nvu binaries to ~/.nvu/bin
13
- * This runs the same logic as the postinstall script.
14
- */ export default function setupCmd(_args) {
14
+ * With --shims: create shims for existing global packages
15
+ */ export default function setupCmd(args) {
15
16
  var binDir = path.join(storagePath, 'bin');
16
17
  // Create directories
17
18
  if (!fs.existsSync(storagePath)) {
@@ -20,6 +21,18 @@ var __dirname = path.dirname(typeof __filename !== 'undefined' ? __filename : ur
20
21
  if (!fs.existsSync(binDir)) {
21
22
  mkdirpSync(binDir);
22
23
  }
24
+ // Check for --shims flag
25
+ var hasShimsFlag = false;
26
+ for(var i = 0; i < args.length; i++){
27
+ if (args[i] === '--shims') {
28
+ hasShimsFlag = true;
29
+ break;
30
+ }
31
+ }
32
+ if (hasShimsFlag) {
33
+ createShimsForGlobalPackages(binDir);
34
+ return;
35
+ }
23
36
  // Find the postinstall script relative to this module
24
37
  var postinstallPath = path.join(__dirname, '..', '..', '..', 'scripts', 'postinstall.cjs');
25
38
  if (fs.existsSync(postinstallPath)) {
@@ -37,3 +50,69 @@ var __dirname = path.dirname(typeof __filename !== 'undefined' ? __filename : ur
37
50
  exit(1);
38
51
  }
39
52
  }
53
+ /**
54
+ * Create shims for all global packages in the default Node version
55
+ */ function createShimsForGlobalPackages(binDir) {
56
+ // Read default version
57
+ var defaultPath = path.join(storagePath, 'default');
58
+ if (!fs.existsSync(defaultPath)) {
59
+ console.log('No default Node version set.');
60
+ console.log('Set one with: nvu default <version>');
61
+ exit(1);
62
+ return;
63
+ }
64
+ var defaultVersion = fs.readFileSync(defaultPath, 'utf8').trim();
65
+ var versionsDir = path.join(storagePath, 'installed');
66
+ // Resolve to exact version
67
+ var matches = findInstalledVersions(versionsDir, defaultVersion);
68
+ if (matches.length === 0) {
69
+ console.log(`Default version ${defaultVersion} is not installed.`);
70
+ exit(1);
71
+ return;
72
+ }
73
+ var resolvedVersion = matches[matches.length - 1];
74
+ var nodeBinDir = path.join(versionsDir, resolvedVersion, 'bin');
75
+ if (!fs.existsSync(nodeBinDir)) {
76
+ console.log(`No bin directory found for ${resolvedVersion}`);
77
+ exit(1);
78
+ return;
79
+ }
80
+ // Get the node shim to copy from
81
+ var nodeShim = path.join(binDir, 'node');
82
+ if (!fs.existsSync(nodeShim)) {
83
+ console.log('Node shim not found. Run: nvu setup');
84
+ exit(1);
85
+ return;
86
+ }
87
+ // Scan binaries in Node's bin directory
88
+ var entries = readdirWithTypes(nodeBinDir);
89
+ var created = 0;
90
+ var skipped = 0;
91
+ for(var i = 0; i < entries.length; i++){
92
+ var entry = entries[i];
93
+ var name = entry.name;
94
+ // Skip our routing shims (node/npm/npx) - don't overwrite them
95
+ if (name === 'node' || name === 'npm' || name === 'npx') {
96
+ continue;
97
+ }
98
+ var shimPath = path.join(binDir, name);
99
+ // Skip if shim already exists
100
+ if (fs.existsSync(shimPath)) {
101
+ skipped++;
102
+ continue;
103
+ }
104
+ // Copy the node shim
105
+ try {
106
+ var shimContent = fs.readFileSync(nodeShim);
107
+ fs.writeFileSync(shimPath, shimContent);
108
+ fs.chmodSync(shimPath, 493); // 0755
109
+ console.log(`Created shim: ${name}`);
110
+ created++;
111
+ } catch (err) {
112
+ console.error(`Failed to create shim for ${name}: ${err.message}`);
113
+ }
114
+ }
115
+ console.log('');
116
+ console.log(`Done. Created ${created} shims, skipped ${skipped} (already exist).`);
117
+ exit(0);
118
+ }
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node-version/node-version-use/src/commands/setup.ts"],"sourcesContent":["import { execSync } from 'child_process';\nimport exit from 'exit-compat';\nimport fs from 'fs';\nimport path from 'path';\nimport url from 'url';\nimport { mkdirpSync } from '../compat.ts';\nimport { storagePath } from '../constants.ts';\n\nvar __dirname = path.dirname(typeof __filename !== 'undefined' ? __filename : url.fileURLToPath(import.meta.url));\n\n/**\n * nvu setup\n *\n * Install/reinstall nvu binaries to ~/.nvu/bin\n * This runs the same logic as the postinstall script.\n */\nexport default function setupCmd(_args: string[]): void {\n var binDir = path.join(storagePath, 'bin');\n\n // Create directories\n if (!fs.existsSync(storagePath)) {\n mkdirpSync(storagePath);\n }\n if (!fs.existsSync(binDir)) {\n mkdirpSync(binDir);\n }\n\n // Find the postinstall script relative to this module\n var postinstallPath = path.join(__dirname, '..', '..', '..', 'scripts', 'postinstall.cjs');\n\n if (fs.existsSync(postinstallPath)) {\n // Run the postinstall script\n try {\n execSync(`node \"${postinstallPath}\"`, { stdio: 'inherit' });\n } catch (_err) {\n // postinstall handles its own errors gracefully\n }\n } else {\n console.log('Setup script not found.');\n console.log('Try reinstalling: npm install -g node-version-use');\n exit(1);\n }\n}\n"],"names":["execSync","exit","fs","path","url","mkdirpSync","storagePath","__dirname","dirname","__filename","fileURLToPath","setupCmd","_args","binDir","join","existsSync","postinstallPath","stdio","_err","console","log"],"mappings":"AAAA,SAASA,QAAQ,QAAQ,gBAAgB;AACzC,OAAOC,UAAU,cAAc;AAC/B,OAAOC,QAAQ,KAAK;AACpB,OAAOC,UAAU,OAAO;AACxB,OAAOC,SAAS,MAAM;AACtB,SAASC,UAAU,QAAQ,eAAe;AAC1C,SAASC,WAAW,QAAQ,kBAAkB;AAE9C,IAAIC,YAAYJ,KAAKK,OAAO,CAAC,OAAOC,eAAe,cAAcA,aAAaL,IAAIM,aAAa,CAAC,YAAYN,GAAG;AAE/G;;;;;CAKC,GACD,eAAe,SAASO,SAASC,KAAe;IAC9C,IAAIC,SAASV,KAAKW,IAAI,CAACR,aAAa;IAEpC,qBAAqB;IACrB,IAAI,CAACJ,GAAGa,UAAU,CAACT,cAAc;QAC/BD,WAAWC;IACb;IACA,IAAI,CAACJ,GAAGa,UAAU,CAACF,SAAS;QAC1BR,WAAWQ;IACb;IAEA,sDAAsD;IACtD,IAAIG,kBAAkBb,KAAKW,IAAI,CAACP,WAAW,MAAM,MAAM,MAAM,WAAW;IAExE,IAAIL,GAAGa,UAAU,CAACC,kBAAkB;QAClC,6BAA6B;QAC7B,IAAI;YACFhB,SAAS,CAAC,MAAM,EAAEgB,gBAAgB,CAAC,CAAC,EAAE;gBAAEC,OAAO;YAAU;QAC3D,EAAE,OAAOC,MAAM;QACb,gDAAgD;QAClD;IACF,OAAO;QACLC,QAAQC,GAAG,CAAC;QACZD,QAAQC,GAAG,CAAC;QACZnB,KAAK;IACP;AACF"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node-version/node-version-use/src/commands/setup.ts"],"sourcesContent":["import { execSync } from 'child_process';\nimport exit from 'exit-compat';\nimport fs from 'fs';\nimport path from 'path';\nimport url from 'url';\nimport { mkdirpSync, readdirWithTypes } from '../compat.ts';\nimport { storagePath } from '../constants.ts';\nimport { findInstalledVersions } from '../lib/findInstalledVersions.ts';\n\nvar __dirname = path.dirname(typeof __filename !== 'undefined' ? __filename : url.fileURLToPath(import.meta.url));\n\n/**\n * nvu setup [--shims]\n *\n * Install/reinstall nvu binaries to ~/.nvu/bin\n * With --shims: create shims for existing global packages\n */\nexport default function setupCmd(args: string[]): void {\n var binDir = path.join(storagePath, 'bin');\n\n // Create directories\n if (!fs.existsSync(storagePath)) {\n mkdirpSync(storagePath);\n }\n if (!fs.existsSync(binDir)) {\n mkdirpSync(binDir);\n }\n\n // Check for --shims flag\n var hasShimsFlag = false;\n for (var i = 0; i < args.length; i++) {\n if (args[i] === '--shims') {\n hasShimsFlag = true;\n break;\n }\n }\n\n if (hasShimsFlag) {\n createShimsForGlobalPackages(binDir);\n return;\n }\n\n // Find the postinstall script relative to this module\n var postinstallPath = path.join(__dirname, '..', '..', '..', 'scripts', 'postinstall.cjs');\n\n if (fs.existsSync(postinstallPath)) {\n // Run the postinstall script\n try {\n execSync(`node \"${postinstallPath}\"`, { stdio: 'inherit' });\n } catch (_err) {\n // postinstall handles its own errors gracefully\n }\n } else {\n console.log('Setup script not found.');\n console.log('Try reinstalling: npm install -g node-version-use');\n exit(1);\n }\n}\n\n/**\n * Create shims for all global packages in the default Node version\n */\nfunction createShimsForGlobalPackages(binDir: string): void {\n // Read default version\n var defaultPath = path.join(storagePath, 'default');\n if (!fs.existsSync(defaultPath)) {\n console.log('No default Node version set.');\n console.log('Set one with: nvu default <version>');\n exit(1);\n return;\n }\n\n var defaultVersion = fs.readFileSync(defaultPath, 'utf8').trim();\n var versionsDir = path.join(storagePath, 'installed');\n\n // Resolve to exact version\n var matches = findInstalledVersions(versionsDir, defaultVersion);\n if (matches.length === 0) {\n console.log(`Default version ${defaultVersion} is not installed.`);\n exit(1);\n return;\n }\n\n var resolvedVersion = matches[matches.length - 1];\n var nodeBinDir = path.join(versionsDir, resolvedVersion, 'bin');\n\n if (!fs.existsSync(nodeBinDir)) {\n console.log(`No bin directory found for ${resolvedVersion}`);\n exit(1);\n return;\n }\n\n // Get the node shim to copy from\n var nodeShim = path.join(binDir, 'node');\n if (!fs.existsSync(nodeShim)) {\n console.log('Node shim not found. Run: nvu setup');\n exit(1);\n return;\n }\n\n // Scan binaries in Node's bin directory\n var entries = readdirWithTypes(nodeBinDir);\n var created = 0;\n var skipped = 0;\n\n for (var i = 0; i < entries.length; i++) {\n var entry = entries[i];\n var name = entry.name;\n\n // Skip our routing shims (node/npm/npx) - don't overwrite them\n if (name === 'node' || name === 'npm' || name === 'npx') {\n continue;\n }\n\n var shimPath = path.join(binDir, name);\n\n // Skip if shim already exists\n if (fs.existsSync(shimPath)) {\n skipped++;\n continue;\n }\n\n // Copy the node shim\n try {\n var shimContent = fs.readFileSync(nodeShim);\n fs.writeFileSync(shimPath, shimContent);\n fs.chmodSync(shimPath, 493); // 0755\n console.log(`Created shim: ${name}`);\n created++;\n } catch (err) {\n console.error(`Failed to create shim for ${name}: ${(err as Error).message}`);\n }\n }\n\n console.log('');\n console.log(`Done. Created ${created} shims, skipped ${skipped} (already exist).`);\n exit(0);\n}\n"],"names":["execSync","exit","fs","path","url","mkdirpSync","readdirWithTypes","storagePath","findInstalledVersions","__dirname","dirname","__filename","fileURLToPath","setupCmd","args","binDir","join","existsSync","hasShimsFlag","i","length","createShimsForGlobalPackages","postinstallPath","stdio","_err","console","log","defaultPath","defaultVersion","readFileSync","trim","versionsDir","matches","resolvedVersion","nodeBinDir","nodeShim","entries","created","skipped","entry","name","shimPath","shimContent","writeFileSync","chmodSync","err","error","message"],"mappings":"AAAA,SAASA,QAAQ,QAAQ,gBAAgB;AACzC,OAAOC,UAAU,cAAc;AAC/B,OAAOC,QAAQ,KAAK;AACpB,OAAOC,UAAU,OAAO;AACxB,OAAOC,SAAS,MAAM;AACtB,SAASC,UAAU,EAAEC,gBAAgB,QAAQ,eAAe;AAC5D,SAASC,WAAW,QAAQ,kBAAkB;AAC9C,SAASC,qBAAqB,QAAQ,kCAAkC;AAExE,IAAIC,YAAYN,KAAKO,OAAO,CAAC,OAAOC,eAAe,cAAcA,aAAaP,IAAIQ,aAAa,CAAC,YAAYR,GAAG;AAE/G;;;;;CAKC,GACD,eAAe,SAASS,SAASC,IAAc;IAC7C,IAAIC,SAASZ,KAAKa,IAAI,CAACT,aAAa;IAEpC,qBAAqB;IACrB,IAAI,CAACL,GAAGe,UAAU,CAACV,cAAc;QAC/BF,WAAWE;IACb;IACA,IAAI,CAACL,GAAGe,UAAU,CAACF,SAAS;QAC1BV,WAAWU;IACb;IAEA,yBAAyB;IACzB,IAAIG,eAAe;IACnB,IAAK,IAAIC,IAAI,GAAGA,IAAIL,KAAKM,MAAM,EAAED,IAAK;QACpC,IAAIL,IAAI,CAACK,EAAE,KAAK,WAAW;YACzBD,eAAe;YACf;QACF;IACF;IAEA,IAAIA,cAAc;QAChBG,6BAA6BN;QAC7B;IACF;IAEA,sDAAsD;IACtD,IAAIO,kBAAkBnB,KAAKa,IAAI,CAACP,WAAW,MAAM,MAAM,MAAM,WAAW;IAExE,IAAIP,GAAGe,UAAU,CAACK,kBAAkB;QAClC,6BAA6B;QAC7B,IAAI;YACFtB,SAAS,CAAC,MAAM,EAAEsB,gBAAgB,CAAC,CAAC,EAAE;gBAAEC,OAAO;YAAU;QAC3D,EAAE,OAAOC,MAAM;QACb,gDAAgD;QAClD;IACF,OAAO;QACLC,QAAQC,GAAG,CAAC;QACZD,QAAQC,GAAG,CAAC;QACZzB,KAAK;IACP;AACF;AAEA;;CAEC,GACD,SAASoB,6BAA6BN,MAAc;IAClD,uBAAuB;IACvB,IAAIY,cAAcxB,KAAKa,IAAI,CAACT,aAAa;IACzC,IAAI,CAACL,GAAGe,UAAU,CAACU,cAAc;QAC/BF,QAAQC,GAAG,CAAC;QACZD,QAAQC,GAAG,CAAC;QACZzB,KAAK;QACL;IACF;IAEA,IAAI2B,iBAAiB1B,GAAG2B,YAAY,CAACF,aAAa,QAAQG,IAAI;IAC9D,IAAIC,cAAc5B,KAAKa,IAAI,CAACT,aAAa;IAEzC,2BAA2B;IAC3B,IAAIyB,UAAUxB,sBAAsBuB,aAAaH;IACjD,IAAII,QAAQZ,MAAM,KAAK,GAAG;QACxBK,QAAQC,GAAG,CAAC,CAAC,gBAAgB,EAAEE,eAAe,kBAAkB,CAAC;QACjE3B,KAAK;QACL;IACF;IAEA,IAAIgC,kBAAkBD,OAAO,CAACA,QAAQZ,MAAM,GAAG,EAAE;IACjD,IAAIc,aAAa/B,KAAKa,IAAI,CAACe,aAAaE,iBAAiB;IAEzD,IAAI,CAAC/B,GAAGe,UAAU,CAACiB,aAAa;QAC9BT,QAAQC,GAAG,CAAC,CAAC,2BAA2B,EAAEO,iBAAiB;QAC3DhC,KAAK;QACL;IACF;IAEA,iCAAiC;IACjC,IAAIkC,WAAWhC,KAAKa,IAAI,CAACD,QAAQ;IACjC,IAAI,CAACb,GAAGe,UAAU,CAACkB,WAAW;QAC5BV,QAAQC,GAAG,CAAC;QACZzB,KAAK;QACL;IACF;IAEA,wCAAwC;IACxC,IAAImC,UAAU9B,iBAAiB4B;IAC/B,IAAIG,UAAU;IACd,IAAIC,UAAU;IAEd,IAAK,IAAInB,IAAI,GAAGA,IAAIiB,QAAQhB,MAAM,EAAED,IAAK;QACvC,IAAIoB,QAAQH,OAAO,CAACjB,EAAE;QACtB,IAAIqB,OAAOD,MAAMC,IAAI;QAErB,+DAA+D;QAC/D,IAAIA,SAAS,UAAUA,SAAS,SAASA,SAAS,OAAO;YACvD;QACF;QAEA,IAAIC,WAAWtC,KAAKa,IAAI,CAACD,QAAQyB;QAEjC,8BAA8B;QAC9B,IAAItC,GAAGe,UAAU,CAACwB,WAAW;YAC3BH;YACA;QACF;QAEA,qBAAqB;QACrB,IAAI;YACF,IAAII,cAAcxC,GAAG2B,YAAY,CAACM;YAClCjC,GAAGyC,aAAa,CAACF,UAAUC;YAC3BxC,GAAG0C,SAAS,CAACH,UAAU,MAAM,OAAO;YACpChB,QAAQC,GAAG,CAAC,CAAC,cAAc,EAAEc,MAAM;YACnCH;QACF,EAAE,OAAOQ,KAAK;YACZpB,QAAQqB,KAAK,CAAC,CAAC,0BAA0B,EAAEN,KAAK,EAAE,EAAE,AAACK,IAAcE,OAAO,EAAE;QAC9E;IACF;IAEAtB,QAAQC,GAAG,CAAC;IACZD,QAAQC,GAAG,CAAC,CAAC,cAAc,EAAEW,QAAQ,gBAAgB,EAAEC,QAAQ,iBAAiB,CAAC;IACjFrC,KAAK;AACP"}