node-version-use 2.4.4 → 2.4.6

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.
@@ -17,6 +17,7 @@ var _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
17
17
  var _path = /*#__PURE__*/ _interop_require_default(require("path"));
18
18
  var _compatts = require("../compat.js");
19
19
  var _constantsts = require("../constants.js");
20
+ var _compareVersionsts = /*#__PURE__*/ _interop_require_default(require("../lib/compareVersions.js"));
20
21
  function _interop_require_default(obj) {
21
22
  return obj && obj.__esModule ? obj : {
22
23
  default: obj
@@ -50,22 +51,8 @@ function listCmd(_args) {
50
51
  if (_fs.default.existsSync(defaultFilePath)) {
51
52
  defaultVersion = _fs.default.readFileSync(defaultFilePath, 'utf8').trim();
52
53
  }
53
- // Sort versions (simple string sort, could be improved with semver)
54
- versions.sort(function(a, b) {
55
- var aParts = a.split('.').map(function(n) {
56
- return parseInt(n, 10) || 0;
57
- });
58
- var bParts = b.split('.').map(function(n) {
59
- return parseInt(n, 10) || 0;
60
- });
61
- for(var i = 0; i < Math.max(aParts.length, bParts.length); i++){
62
- var aVal = aParts[i] || 0;
63
- var bVal = bParts[i] || 0;
64
- if (aVal !== bVal) return bVal - aVal; // Descending order
65
- }
66
- return 0;
67
- });
68
54
  console.log('Installed Node versions:');
55
+ versions.sort(_compareVersionsts.default);
69
56
  for(var i = 0; i < versions.length; i++){
70
57
  var version = versions[i];
71
58
  var isDefault = version === defaultVersion || "v".concat(version) === defaultVersion || version === "v".concat(defaultVersion);
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node-version/node-version-use/src/commands/list.ts"],"sourcesContent":["import exit from 'exit-compat';\nimport fs from 'fs';\nimport path from 'path';\nimport { readdirWithTypes } from '../compat.ts';\nimport { storagePath } from '../constants.ts';\n\n/**\n * nvu list\n *\n * List all installed Node versions.\n */\nexport default function listCmd(_args: string[]): void {\n const versionsPath = path.join(storagePath, 'installed');\n\n // Check if versions directory exists\n if (!fs.existsSync(versionsPath)) {\n console.log('No Node versions installed.');\n console.log('Install a version: nvu install <version>');\n exit(0);\n return;\n }\n\n // Read all directories in versions folder\n const entries = readdirWithTypes(versionsPath);\n const versions = entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);\n\n if (versions.length === 0) {\n console.log('No Node versions installed.');\n console.log('Install a version: nvu install <version>');\n exit(0);\n return;\n }\n\n // Get the current default\n const defaultFilePath = path.join(storagePath, 'default');\n let defaultVersion = '';\n if (fs.existsSync(defaultFilePath)) {\n defaultVersion = fs.readFileSync(defaultFilePath, 'utf8').trim();\n }\n\n // Sort versions (simple string sort, could be improved with semver)\n versions.sort((a, b) => {\n const aParts = a.split('.').map((n) => parseInt(n, 10) || 0);\n const bParts = b.split('.').map((n) => parseInt(n, 10) || 0);\n for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {\n const aVal = aParts[i] || 0;\n const bVal = bParts[i] || 0;\n if (aVal !== bVal) return bVal - aVal; // Descending order\n }\n return 0;\n });\n\n console.log('Installed Node versions:');\n for (let i = 0; i < versions.length; i++) {\n const version = versions[i];\n const isDefault = version === defaultVersion || `v${version}` === defaultVersion || version === `v${defaultVersion}`;\n const marker = isDefault ? ' (default)' : '';\n console.log(` ${version}${marker}`);\n }\n exit(0);\n}\n"],"names":["listCmd","_args","versionsPath","path","join","storagePath","fs","existsSync","console","log","exit","entries","readdirWithTypes","versions","filter","entry","isDirectory","map","name","length","defaultFilePath","defaultVersion","readFileSync","trim","sort","a","b","aParts","split","n","parseInt","bParts","i","Math","max","aVal","bVal","version","isDefault","marker"],"mappings":";;;;+BAMA;;;;CAIC,GACD;;;eAAwBA;;;iEAXP;yDACF;2DACE;wBACgB;2BACL;;;;;;AAOb,SAASA,QAAQC,KAAe;IAC7C,IAAMC,eAAeC,aAAI,CAACC,IAAI,CAACC,wBAAW,EAAE;IAE5C,qCAAqC;IACrC,IAAI,CAACC,WAAE,CAACC,UAAU,CAACL,eAAe;QAChCM,QAAQC,GAAG,CAAC;QACZD,QAAQC,GAAG,CAAC;QACZC,IAAAA,mBAAI,EAAC;QACL;IACF;IAEA,0CAA0C;IAC1C,IAAMC,UAAUC,IAAAA,0BAAgB,EAACV;IACjC,IAAMW,WAAWF,QAAQG,MAAM,CAAC,SAACC;eAAUA,MAAMC,WAAW;OAAIC,GAAG,CAAC,SAACF;eAAUA,MAAMG,IAAI;;IAEzF,IAAIL,SAASM,MAAM,KAAK,GAAG;QACzBX,QAAQC,GAAG,CAAC;QACZD,QAAQC,GAAG,CAAC;QACZC,IAAAA,mBAAI,EAAC;QACL;IACF;IAEA,0BAA0B;IAC1B,IAAMU,kBAAkBjB,aAAI,CAACC,IAAI,CAACC,wBAAW,EAAE;IAC/C,IAAIgB,iBAAiB;IACrB,IAAIf,WAAE,CAACC,UAAU,CAACa,kBAAkB;QAClCC,iBAAiBf,WAAE,CAACgB,YAAY,CAACF,iBAAiB,QAAQG,IAAI;IAChE;IAEA,oEAAoE;IACpEV,SAASW,IAAI,CAAC,SAACC,GAAGC;QAChB,IAAMC,SAASF,EAAEG,KAAK,CAAC,KAAKX,GAAG,CAAC,SAACY;mBAAMC,SAASD,GAAG,OAAO;;QAC1D,IAAME,SAASL,EAAEE,KAAK,CAAC,KAAKX,GAAG,CAAC,SAACY;mBAAMC,SAASD,GAAG,OAAO;;QAC1D,IAAK,IAAIG,IAAI,GAAGA,IAAIC,KAAKC,GAAG,CAACP,OAAOR,MAAM,EAAEY,OAAOZ,MAAM,GAAGa,IAAK;YAC/D,IAAMG,OAAOR,MAAM,CAACK,EAAE,IAAI;YAC1B,IAAMI,OAAOL,MAAM,CAACC,EAAE,IAAI;YAC1B,IAAIG,SAASC,MAAM,OAAOA,OAAOD,MAAM,mBAAmB;QAC5D;QACA,OAAO;IACT;IAEA3B,QAAQC,GAAG,CAAC;IACZ,IAAK,IAAIuB,IAAI,GAAGA,IAAInB,SAASM,MAAM,EAAEa,IAAK;QACxC,IAAMK,UAAUxB,QAAQ,CAACmB,EAAE;QAC3B,IAAMM,YAAYD,YAAYhB,kBAAkB,AAAC,IAAW,OAARgB,aAAchB,kBAAkBgB,YAAY,AAAC,IAAkB,OAAfhB;QACpG,IAAMkB,SAASD,YAAY,eAAe;QAC1C9B,QAAQC,GAAG,CAAC,AAAC,KAAc8B,OAAVF,SAAiB,OAAPE;IAC7B;IACA7B,IAAAA,mBAAI,EAAC;AACP"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node-version/node-version-use/src/commands/list.ts"],"sourcesContent":["import exit from 'exit-compat';\nimport fs from 'fs';\nimport path from 'path';\nimport { readdirWithTypes } from '../compat.ts';\nimport { storagePath } from '../constants.ts';\nimport compareVersions from '../lib/compareVersions.ts';\n\n/**\n * nvu list\n *\n * List all installed Node versions.\n */\nexport default function listCmd(_args: string[]): void {\n const versionsPath = path.join(storagePath, 'installed');\n\n // Check if versions directory exists\n if (!fs.existsSync(versionsPath)) {\n console.log('No Node versions installed.');\n console.log('Install a version: nvu install <version>');\n exit(0);\n return;\n }\n\n // Read all directories in versions folder\n const entries = readdirWithTypes(versionsPath);\n const versions = entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);\n\n if (versions.length === 0) {\n console.log('No Node versions installed.');\n console.log('Install a version: nvu install <version>');\n exit(0);\n return;\n }\n\n // Get the current default\n const defaultFilePath = path.join(storagePath, 'default');\n let defaultVersion = '';\n if (fs.existsSync(defaultFilePath)) {\n defaultVersion = fs.readFileSync(defaultFilePath, 'utf8').trim();\n }\n\n console.log('Installed Node versions:');\n versions.sort(compareVersions);\n for (let i = 0; i < versions.length; i++) {\n const version = versions[i];\n const isDefault = version === defaultVersion || `v${version}` === defaultVersion || version === `v${defaultVersion}`;\n const marker = isDefault ? ' (default)' : '';\n console.log(` ${version}${marker}`);\n }\n exit(0);\n}\n"],"names":["listCmd","_args","versionsPath","path","join","storagePath","fs","existsSync","console","log","exit","entries","readdirWithTypes","versions","filter","entry","isDirectory","map","name","length","defaultFilePath","defaultVersion","readFileSync","trim","sort","compareVersions","i","version","isDefault","marker"],"mappings":";;;;+BAOA;;;;CAIC,GACD;;;eAAwBA;;;iEAZP;yDACF;2DACE;wBACgB;2BACL;wEACA;;;;;;AAOb,SAASA,QAAQC,KAAe;IAC7C,IAAMC,eAAeC,aAAI,CAACC,IAAI,CAACC,wBAAW,EAAE;IAE5C,qCAAqC;IACrC,IAAI,CAACC,WAAE,CAACC,UAAU,CAACL,eAAe;QAChCM,QAAQC,GAAG,CAAC;QACZD,QAAQC,GAAG,CAAC;QACZC,IAAAA,mBAAI,EAAC;QACL;IACF;IAEA,0CAA0C;IAC1C,IAAMC,UAAUC,IAAAA,0BAAgB,EAACV;IACjC,IAAMW,WAAWF,QAAQG,MAAM,CAAC,SAACC;eAAUA,MAAMC,WAAW;OAAIC,GAAG,CAAC,SAACF;eAAUA,MAAMG,IAAI;;IAEzF,IAAIL,SAASM,MAAM,KAAK,GAAG;QACzBX,QAAQC,GAAG,CAAC;QACZD,QAAQC,GAAG,CAAC;QACZC,IAAAA,mBAAI,EAAC;QACL;IACF;IAEA,0BAA0B;IAC1B,IAAMU,kBAAkBjB,aAAI,CAACC,IAAI,CAACC,wBAAW,EAAE;IAC/C,IAAIgB,iBAAiB;IACrB,IAAIf,WAAE,CAACC,UAAU,CAACa,kBAAkB;QAClCC,iBAAiBf,WAAE,CAACgB,YAAY,CAACF,iBAAiB,QAAQG,IAAI;IAChE;IAEAf,QAAQC,GAAG,CAAC;IACZI,SAASW,IAAI,CAACC,0BAAe;IAC7B,IAAK,IAAIC,IAAI,GAAGA,IAAIb,SAASM,MAAM,EAAEO,IAAK;QACxC,IAAMC,UAAUd,QAAQ,CAACa,EAAE;QAC3B,IAAME,YAAYD,YAAYN,kBAAkB,AAAC,IAAW,OAARM,aAAcN,kBAAkBM,YAAY,AAAC,IAAkB,OAAfN;QACpG,IAAMQ,SAASD,YAAY,eAAe;QAC1CpB,QAAQC,GAAG,CAAC,AAAC,KAAcoB,OAAVF,SAAiB,OAAPE;IAC7B;IACAnB,IAAAA,mBAAI,EAAC;AACP"}
package/dist/cjs/index.js CHANGED
@@ -20,7 +20,7 @@ function nodeVersionUse(versionExpression, command, args, options, callback) {
20
20
  if (typeof callback === 'function') return (0, _workerts.default)(versionExpression, command, args, options, callback);
21
21
  return new Promise(function(resolve, reject) {
22
22
  return (0, _workerts.default)(versionExpression, command, args, options, function(err, result) {
23
- err ? reject(err) : resolve(result);
23
+ return err ? reject(err) : resolve(result);
24
24
  });
25
25
  });
26
26
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node-version/node-version-use/src/index.ts"],"sourcesContent":["import type { UseCallback, UseOptions, UseResult } from './types.ts';\nimport worker from './worker.ts';\n\nexport type * from './types.ts';\n\nexport default function nodeVersionUse(versionExpression: string, command: string, args: string[]): Promise<UseResult[]>;\nexport default function nodeVersionUse(versionExpression: string, command: string, args: string[], options: UseOptions): Promise<UseResult[]>;\n\nexport default function nodeVersionUse(versionExpression: string, command: string, args: string[], callback: UseCallback): void;\nexport default function nodeVersionUse(versionExpression: string, command: string, args: string[], options: UseOptions, callback: UseCallback): void;\n\nexport default function nodeVersionUse(versionExpression: string, command: string, args: string[], options?: UseOptions | UseCallback, callback?: UseCallback): void | Promise<UseResult[]> {\n callback = typeof options === 'function' ? options : callback;\n options = typeof options === 'function' ? {} : ((options || {}) as UseOptions);\n\n if (typeof callback === 'function') return worker(versionExpression, command, args, options, callback);\n return new Promise((resolve, reject) =>\n worker(versionExpression, command, args, options, (err, result) => {\n err ? reject(err) : resolve(result);\n })\n );\n}\n"],"names":["nodeVersionUse","versionExpression","command","args","options","callback","worker","Promise","resolve","reject","err","result"],"mappings":";;;;+BAWA;;;eAAwBA;;;+DAVL;;;;;;AAUJ,SAASA,eAAeC,iBAAyB,EAAEC,OAAe,EAAEC,IAAc,EAAEC,OAAkC,EAAEC,QAAsB;IAC3JA,WAAW,OAAOD,YAAY,aAAaA,UAAUC;IACrDD,UAAU,OAAOA,YAAY,aAAa,CAAC,IAAMA,WAAW,CAAC;IAE7D,IAAI,OAAOC,aAAa,YAAY,OAAOC,IAAAA,iBAAM,EAACL,mBAAmBC,SAASC,MAAMC,SAASC;IAC7F,OAAO,IAAIE,QAAQ,SAACC,SAASC;eAC3BH,IAAAA,iBAAM,EAACL,mBAAmBC,SAASC,MAAMC,SAAS,SAACM,KAAKC;YACtDD,MAAMD,OAAOC,OAAOF,QAAQG;QAC9B;;AAEJ"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node-version/node-version-use/src/index.ts"],"sourcesContent":["import type { UseCallback, UseOptions, UseResult } from './types.ts';\nimport worker from './worker.ts';\n\nexport type * from './types.ts';\n\nexport default function nodeVersionUse(versionExpression: string, command: string, args: string[]): Promise<UseResult[]>;\nexport default function nodeVersionUse(versionExpression: string, command: string, args: string[], options: UseOptions): Promise<UseResult[]>;\n\nexport default function nodeVersionUse(versionExpression: string, command: string, args: string[], callback: UseCallback): void;\nexport default function nodeVersionUse(versionExpression: string, command: string, args: string[], options: UseOptions, callback: UseCallback): void;\n\nexport default function nodeVersionUse(versionExpression: string, command: string, args: string[], options?: UseOptions | UseCallback, callback?: UseCallback): void | Promise<UseResult[]> {\n callback = typeof options === 'function' ? options : callback;\n options = typeof options === 'function' ? {} : ((options || {}) as UseOptions);\n\n if (typeof callback === 'function') return worker(versionExpression, command, args, options, callback);\n return new Promise((resolve, reject) => worker(versionExpression, command, args, options, (err, result) => (err ? reject(err) : resolve(result))));\n}\n"],"names":["nodeVersionUse","versionExpression","command","args","options","callback","worker","Promise","resolve","reject","err","result"],"mappings":";;;;+BAWA;;;eAAwBA;;;+DAVL;;;;;;AAUJ,SAASA,eAAeC,iBAAyB,EAAEC,OAAe,EAAEC,IAAc,EAAEC,OAAkC,EAAEC,QAAsB;IAC3JA,WAAW,OAAOD,YAAY,aAAaA,UAAUC;IACrDD,UAAU,OAAOA,YAAY,aAAa,CAAC,IAAMA,WAAW,CAAC;IAE7D,IAAI,OAAOC,aAAa,YAAY,OAAOC,IAAAA,iBAAM,EAACL,mBAAmBC,SAASC,MAAMC,SAASC;IAC7F,OAAO,IAAIE,QAAQ,SAACC,SAASC;eAAWH,IAAAA,iBAAM,EAACL,mBAAmBC,SAASC,MAAMC,SAAS,SAACM,KAAKC;mBAAYD,MAAMD,OAAOC,OAAOF,QAAQG;;;AAC1I"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Compare two semver version strings (e.g., "20.19.0" vs "20.9.1")
3
+ * Returns: negative if a < b, positive if a > b, 0 if equal
4
+ */
5
+ export default function compareVersions(a: string, b: string): number;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Compare two semver version strings (e.g., "20.19.0" vs "20.9.1")
3
+ * Returns: negative if a < b, positive if a > b, 0 if equal
4
+ */
5
+ export default function compareVersions(a: string, b: string): number;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Compare two semver version strings (e.g., "20.19.0" vs "20.9.1")
3
+ * Returns: negative if a < b, positive if a > b, 0 if equal
4
+ */ "use strict";
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ Object.defineProperty(exports, "default", {
9
+ enumerable: true,
10
+ get: function() {
11
+ return compareVersions;
12
+ }
13
+ });
14
+ function compareVersions(a, b) {
15
+ var aParts = a.replace(/^v/, '').split('.');
16
+ var bParts = b.replace(/^v/, '').split('.');
17
+ var len = Math.max(aParts.length, bParts.length);
18
+ for(var i = 0; i < len; i++){
19
+ var aNum = parseInt(aParts[i], 10) || 0;
20
+ var bNum = parseInt(bParts[i], 10) || 0;
21
+ if (aNum !== bNum) return aNum - bNum;
22
+ }
23
+ return 0;
24
+ }
25
+ /* 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/lib/compareVersions.ts"],"sourcesContent":["/**\n * Compare two semver version strings (e.g., \"20.19.0\" vs \"20.9.1\")\n * Returns: negative if a < b, positive if a > b, 0 if equal\n */\nexport default function compareVersions(a: string, b: string): number {\n const aParts = a.replace(/^v/, '').split('.');\n const bParts = b.replace(/^v/, '').split('.');\n const len = Math.max(aParts.length, bParts.length);\n\n for (let i = 0; i < len; i++) {\n const aNum = parseInt(aParts[i], 10) || 0;\n const bNum = parseInt(bParts[i], 10) || 0;\n if (aNum !== bNum) return aNum - bNum;\n }\n return 0;\n}\n"],"names":["compareVersions","a","b","aParts","replace","split","bParts","len","Math","max","length","i","aNum","parseInt","bNum"],"mappings":"AAAA;;;CAGC;;;;+BACD;;;eAAwBA;;;AAAT,SAASA,gBAAgBC,CAAS,EAAEC,CAAS;IAC1D,IAAMC,SAASF,EAAEG,OAAO,CAAC,MAAM,IAAIC,KAAK,CAAC;IACzC,IAAMC,SAASJ,EAAEE,OAAO,CAAC,MAAM,IAAIC,KAAK,CAAC;IACzC,IAAME,MAAMC,KAAKC,GAAG,CAACN,OAAOO,MAAM,EAAEJ,OAAOI,MAAM;IAEjD,IAAK,IAAIC,IAAI,GAAGA,IAAIJ,KAAKI,IAAK;QAC5B,IAAMC,OAAOC,SAASV,MAAM,CAACQ,EAAE,EAAE,OAAO;QACxC,IAAMG,OAAOD,SAASP,MAAM,CAACK,EAAE,EAAE,OAAO;QACxC,IAAIC,SAASE,MAAM,OAAOF,OAAOE;IACnC;IACA,OAAO;AACT"}
@@ -19,27 +19,12 @@ _export(exports, {
19
19
  var _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
20
20
  var _path = /*#__PURE__*/ _interop_require_default(require("path"));
21
21
  var _compatts = require("../compat.js");
22
+ var _compareVersionsts = /*#__PURE__*/ _interop_require_default(require("./compareVersions.js"));
22
23
  function _interop_require_default(obj) {
23
24
  return obj && obj.__esModule ? obj : {
24
25
  default: obj
25
26
  };
26
27
  }
27
- /**
28
- * Compare two semver version strings (e.g., "20.19.0" vs "20.9.1")
29
- * Returns: negative if a < b, positive if a > b, 0 if equal
30
- */ function compareVersions(a, b) {
31
- var aParts = a.replace(/^v/, '').split('.');
32
- var bParts = b.replace(/^v/, '').split('.');
33
- var len = Math.max(aParts.length, bParts.length);
34
- for(var i = 0; i < len; i++){
35
- var aNum = parseInt(aParts[i], 10) || 0;
36
- var bNum = parseInt(bParts[i], 10) || 0;
37
- if (aNum !== bNum) {
38
- return aNum - bNum;
39
- }
40
- }
41
- return 0;
42
- }
43
28
  function findInstalledVersions(versionsPath, version) {
44
29
  if (!_fs.default.existsSync(versionsPath)) {
45
30
  return [];
@@ -76,8 +61,7 @@ function findInstalledVersions(versionsPath, version) {
76
61
  }
77
62
  }
78
63
  // Sort by semver (ascending) so highest version is last
79
- matches.sort(compareVersions);
80
- return matches;
64
+ return matches.sort(_compareVersionsts.default);
81
65
  }
82
66
  function getAllInstalledVersions(versionsPath) {
83
67
  if (!_fs.default.existsSync(versionsPath)) {
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node-version/node-version-use/src/lib/findInstalledVersions.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\nimport { readdirWithTypes } from '../compat.ts';\n\n/**\n * Compare two semver version strings (e.g., \"20.19.0\" vs \"20.9.1\")\n * Returns: negative if a < b, positive if a > b, 0 if equal\n */\nfunction compareVersions(a: string, b: string): number {\n const aParts = a.replace(/^v/, '').split('.');\n const bParts = b.replace(/^v/, '').split('.');\n const len = Math.max(aParts.length, bParts.length);\n\n for (let i = 0; i < len; i++) {\n const aNum = parseInt(aParts[i], 10) || 0;\n const bNum = parseInt(bParts[i], 10) || 0;\n if (aNum !== bNum) {\n return aNum - bNum;\n }\n }\n return 0;\n}\n\n/**\n * Find all installed versions matching the given version string\n * Results are sorted in ascending semver order (lowest first, highest last)\n */\nexport function findInstalledVersions(versionsPath: string, version: string): string[] {\n if (!fs.existsSync(versionsPath)) {\n return [];\n }\n\n const normalizedVersion = version.replace(/^v/, '');\n const matches: string[] = [];\n\n // Try exact matches first\n const exactMatches = [version, `v${normalizedVersion}`, normalizedVersion];\n for (let i = 0; i < exactMatches.length; i++) {\n const v = exactMatches[i];\n const versionPath = path.join(versionsPath, v);\n if (fs.existsSync(versionPath) && fs.statSync(versionPath).isDirectory()) {\n if (matches.indexOf(v) === -1) {\n matches.push(v);\n }\n }\n }\n\n // If we have an exact match, return just that\n if (matches.length > 0) {\n return matches;\n }\n\n // Try partial match (e.g., \"20\" matches \"v20.19.6\")\n const entries = readdirWithTypes(versionsPath);\n for (let j = 0; j < entries.length; j++) {\n const entry = entries[j];\n if (!entry.isDirectory()) continue;\n const dirVersion = entry.name.replace(/^v/, '');\n if (dirVersion.indexOf(`${normalizedVersion}.`) === 0) {\n matches.push(entry.name);\n }\n }\n\n // Sort by semver (ascending) so highest version is last\n matches.sort(compareVersions);\n\n return matches;\n}\n\n/**\n * Get all installed versions\n */\nexport function getAllInstalledVersions(versionsPath: string): string[] {\n if (!fs.existsSync(versionsPath)) {\n return [];\n }\n\n const entries = readdirWithTypes(versionsPath);\n const versions: string[] = [];\n for (let i = 0; i < entries.length; i++) {\n if (entries[i].isDirectory()) {\n versions.push(entries[i].name);\n }\n }\n\n return versions;\n}\n"],"names":["findInstalledVersions","getAllInstalledVersions","compareVersions","a","b","aParts","replace","split","bParts","len","Math","max","length","i","aNum","parseInt","bNum","versionsPath","version","fs","existsSync","normalizedVersion","matches","exactMatches","v","versionPath","path","join","statSync","isDirectory","indexOf","push","entries","readdirWithTypes","j","entry","dirVersion","name","sort","versions"],"mappings":";;;;;;;;;;;QA2BgBA;eAAAA;;QA6CAC;eAAAA;;;yDAxED;2DACE;wBACgB;;;;;;AAEjC;;;CAGC,GACD,SAASC,gBAAgBC,CAAS,EAAEC,CAAS;IAC3C,IAAMC,SAASF,EAAEG,OAAO,CAAC,MAAM,IAAIC,KAAK,CAAC;IACzC,IAAMC,SAASJ,EAAEE,OAAO,CAAC,MAAM,IAAIC,KAAK,CAAC;IACzC,IAAME,MAAMC,KAAKC,GAAG,CAACN,OAAOO,MAAM,EAAEJ,OAAOI,MAAM;IAEjD,IAAK,IAAIC,IAAI,GAAGA,IAAIJ,KAAKI,IAAK;QAC5B,IAAMC,OAAOC,SAASV,MAAM,CAACQ,EAAE,EAAE,OAAO;QACxC,IAAMG,OAAOD,SAASP,MAAM,CAACK,EAAE,EAAE,OAAO;QACxC,IAAIC,SAASE,MAAM;YACjB,OAAOF,OAAOE;QAChB;IACF;IACA,OAAO;AACT;AAMO,SAAShB,sBAAsBiB,YAAoB,EAAEC,OAAe;IACzE,IAAI,CAACC,WAAE,CAACC,UAAU,CAACH,eAAe;QAChC,OAAO,EAAE;IACX;IAEA,IAAMI,oBAAoBH,QAAQZ,OAAO,CAAC,MAAM;IAChD,IAAMgB,UAAoB,EAAE;IAE5B,0BAA0B;IAC1B,IAAMC,eAAe;QAACL;QAAU,IAAqB,OAAlBG;QAAqBA;KAAkB;IAC1E,IAAK,IAAIR,IAAI,GAAGA,IAAIU,aAAaX,MAAM,EAAEC,IAAK;QAC5C,IAAMW,IAAID,YAAY,CAACV,EAAE;QACzB,IAAMY,cAAcC,aAAI,CAACC,IAAI,CAACV,cAAcO;QAC5C,IAAIL,WAAE,CAACC,UAAU,CAACK,gBAAgBN,WAAE,CAACS,QAAQ,CAACH,aAAaI,WAAW,IAAI;YACxE,IAAIP,QAAQQ,OAAO,CAACN,OAAO,CAAC,GAAG;gBAC7BF,QAAQS,IAAI,CAACP;YACf;QACF;IACF;IAEA,8CAA8C;IAC9C,IAAIF,QAAQV,MAAM,GAAG,GAAG;QACtB,OAAOU;IACT;IAEA,oDAAoD;IACpD,IAAMU,UAAUC,IAAAA,0BAAgB,EAAChB;IACjC,IAAK,IAAIiB,IAAI,GAAGA,IAAIF,QAAQpB,MAAM,EAAEsB,IAAK;QACvC,IAAMC,QAAQH,OAAO,CAACE,EAAE;QACxB,IAAI,CAACC,MAAMN,WAAW,IAAI;QAC1B,IAAMO,aAAaD,MAAME,IAAI,CAAC/B,OAAO,CAAC,MAAM;QAC5C,IAAI8B,WAAWN,OAAO,CAAC,AAAC,GAAoB,OAAlBT,mBAAkB,UAAQ,GAAG;YACrDC,QAAQS,IAAI,CAACI,MAAME,IAAI;QACzB;IACF;IAEA,wDAAwD;IACxDf,QAAQgB,IAAI,CAACpC;IAEb,OAAOoB;AACT;AAKO,SAASrB,wBAAwBgB,YAAoB;IAC1D,IAAI,CAACE,WAAE,CAACC,UAAU,CAACH,eAAe;QAChC,OAAO,EAAE;IACX;IAEA,IAAMe,UAAUC,IAAAA,0BAAgB,EAAChB;IACjC,IAAMsB,WAAqB,EAAE;IAC7B,IAAK,IAAI1B,IAAI,GAAGA,IAAImB,QAAQpB,MAAM,EAAEC,IAAK;QACvC,IAAImB,OAAO,CAACnB,EAAE,CAACgB,WAAW,IAAI;YAC5BU,SAASR,IAAI,CAACC,OAAO,CAACnB,EAAE,CAACwB,IAAI;QAC/B;IACF;IAEA,OAAOE;AACT"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node-version/node-version-use/src/lib/findInstalledVersions.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\nimport { readdirWithTypes } from '../compat.ts';\nimport compareVersions from './compareVersions.ts';\n\n/**\n * Find all installed versions matching the given version string\n * Results are sorted in ascending semver order (lowest first, highest last)\n */\nexport function findInstalledVersions(versionsPath: string, version: string): string[] {\n if (!fs.existsSync(versionsPath)) {\n return [];\n }\n\n const normalizedVersion = version.replace(/^v/, '');\n const matches: string[] = [];\n\n // Try exact matches first\n const exactMatches = [version, `v${normalizedVersion}`, normalizedVersion];\n for (let i = 0; i < exactMatches.length; i++) {\n const v = exactMatches[i];\n const versionPath = path.join(versionsPath, v);\n if (fs.existsSync(versionPath) && fs.statSync(versionPath).isDirectory()) {\n if (matches.indexOf(v) === -1) {\n matches.push(v);\n }\n }\n }\n\n // If we have an exact match, return just that\n if (matches.length > 0) {\n return matches;\n }\n\n // Try partial match (e.g., \"20\" matches \"v20.19.6\")\n const entries = readdirWithTypes(versionsPath);\n for (let j = 0; j < entries.length; j++) {\n const entry = entries[j];\n if (!entry.isDirectory()) continue;\n const dirVersion = entry.name.replace(/^v/, '');\n if (dirVersion.indexOf(`${normalizedVersion}.`) === 0) {\n matches.push(entry.name);\n }\n }\n\n // Sort by semver (ascending) so highest version is last\n return matches.sort(compareVersions);\n}\n\n/**\n * Get all installed versions\n */\nexport function getAllInstalledVersions(versionsPath: string): string[] {\n if (!fs.existsSync(versionsPath)) {\n return [];\n }\n\n const entries = readdirWithTypes(versionsPath);\n const versions: string[] = [];\n for (let i = 0; i < entries.length; i++) {\n if (entries[i].isDirectory()) {\n versions.push(entries[i].name);\n }\n }\n\n return versions;\n}\n"],"names":["findInstalledVersions","getAllInstalledVersions","versionsPath","version","fs","existsSync","normalizedVersion","replace","matches","exactMatches","i","length","v","versionPath","path","join","statSync","isDirectory","indexOf","push","entries","readdirWithTypes","j","entry","dirVersion","name","sort","compareVersions","versions"],"mappings":";;;;;;;;;;;QASgBA;eAAAA;;QA2CAC;eAAAA;;;yDApDD;2DACE;wBACgB;wEACL;;;;;;AAMrB,SAASD,sBAAsBE,YAAoB,EAAEC,OAAe;IACzE,IAAI,CAACC,WAAE,CAACC,UAAU,CAACH,eAAe;QAChC,OAAO,EAAE;IACX;IAEA,IAAMI,oBAAoBH,QAAQI,OAAO,CAAC,MAAM;IAChD,IAAMC,UAAoB,EAAE;IAE5B,0BAA0B;IAC1B,IAAMC,eAAe;QAACN;QAAU,IAAqB,OAAlBG;QAAqBA;KAAkB;IAC1E,IAAK,IAAII,IAAI,GAAGA,IAAID,aAAaE,MAAM,EAAED,IAAK;QAC5C,IAAME,IAAIH,YAAY,CAACC,EAAE;QACzB,IAAMG,cAAcC,aAAI,CAACC,IAAI,CAACb,cAAcU;QAC5C,IAAIR,WAAE,CAACC,UAAU,CAACQ,gBAAgBT,WAAE,CAACY,QAAQ,CAACH,aAAaI,WAAW,IAAI;YACxE,IAAIT,QAAQU,OAAO,CAACN,OAAO,CAAC,GAAG;gBAC7BJ,QAAQW,IAAI,CAACP;YACf;QACF;IACF;IAEA,8CAA8C;IAC9C,IAAIJ,QAAQG,MAAM,GAAG,GAAG;QACtB,OAAOH;IACT;IAEA,oDAAoD;IACpD,IAAMY,UAAUC,IAAAA,0BAAgB,EAACnB;IACjC,IAAK,IAAIoB,IAAI,GAAGA,IAAIF,QAAQT,MAAM,EAAEW,IAAK;QACvC,IAAMC,QAAQH,OAAO,CAACE,EAAE;QACxB,IAAI,CAACC,MAAMN,WAAW,IAAI;QAC1B,IAAMO,aAAaD,MAAME,IAAI,CAAClB,OAAO,CAAC,MAAM;QAC5C,IAAIiB,WAAWN,OAAO,CAAC,AAAC,GAAoB,OAAlBZ,mBAAkB,UAAQ,GAAG;YACrDE,QAAQW,IAAI,CAACI,MAAME,IAAI;QACzB;IACF;IAEA,wDAAwD;IACxD,OAAOjB,QAAQkB,IAAI,CAACC,0BAAe;AACrC;AAKO,SAAS1B,wBAAwBC,YAAoB;IAC1D,IAAI,CAACE,WAAE,CAACC,UAAU,CAACH,eAAe;QAChC,OAAO,EAAE;IACX;IAEA,IAAMkB,UAAUC,IAAAA,0BAAgB,EAACnB;IACjC,IAAM0B,WAAqB,EAAE;IAC7B,IAAK,IAAIlB,IAAI,GAAGA,IAAIU,QAAQT,MAAM,EAAED,IAAK;QACvC,IAAIU,OAAO,CAACV,EAAE,CAACO,WAAW,IAAI;YAC5BW,SAAST,IAAI,CAACC,OAAO,CAACV,EAAE,CAACe,IAAI;QAC/B;IACF;IAEA,OAAOG;AACT"}
@@ -1,10 +1,11 @@
1
1
  /**
2
- * Find a system binary by searching PATH, excluding ~/.nvu/bin
2
+ * Find a system binary by searching PATH, excluding ~/.nvu/bin and version directories
3
3
  * Returns the full path to the binary, or null if not found
4
+ * NOTE: Keep in sync with Node.js resolveSystemBinary
4
5
  */
5
6
  export declare function resolveSystemBinary(name: string): string | null;
6
7
  /**
7
- * Get PATH with ~/.nvu/bin removed
8
+ * Get PATH with ~/.nvu/bin and version directories removed
8
9
  * Used to create an environment for spawning system commands
9
10
  */
10
11
  export declare function getPathWithoutNvuBin(): string;
@@ -1,10 +1,11 @@
1
1
  /**
2
- * Find a system binary by searching PATH, excluding ~/.nvu/bin
2
+ * Find a system binary by searching PATH, excluding ~/.nvu/bin and version directories
3
3
  * Returns the full path to the binary, or null if not found
4
+ * NOTE: Keep in sync with Node.js resolveSystemBinary
4
5
  */
5
6
  export declare function resolveSystemBinary(name: string): string | null;
6
7
  /**
7
- * Get PATH with ~/.nvu/bin removed
8
+ * Get PATH with ~/.nvu/bin and version directories removed
8
9
  * Used to create an environment for spawning system commands
9
10
  */
10
11
  export declare function getPathWithoutNvuBin(): string;
@@ -1,7 +1,4 @@
1
- /**
2
- * Resolve system binaries by searching PATH while excluding ~/.nvu/bin
3
- * This mirrors the Go binary's findSystemBinary() function
4
- */ "use strict";
1
+ "use strict";
5
2
  Object.defineProperty(exports, "__esModule", {
6
3
  value: true
7
4
  });
@@ -30,6 +27,7 @@ function _interop_require_default(obj) {
30
27
  }
31
28
  var isWindows = process.platform === 'win32' || /^(msys|cygwin)$/.test(process.env.OSTYPE);
32
29
  var nvuBinDir = _path.default.join((0, _compatts.homedir)(), '.nvu', 'bin');
30
+ var nvuInstalledDir = _path.default.join((0, _compatts.homedir)(), '.nvu', 'installed');
33
31
  var pathKey = (0, _envpathkey.default)(); // PATH or Path or similar
34
32
  var pathDelimiter = _path.default.delimiter ? _path.default.delimiter : isWindows ? ';' : ':';
35
33
  /**
@@ -39,11 +37,12 @@ var pathDelimiter = _path.default.delimiter ? _path.default.delimiter : isWindow
39
37
  return a === b;
40
38
  }
41
39
  /**
42
- * Check if a path is within the nvu bin directory
43
- */ function isInNvuBin(filePath) {
40
+ * Check if a path is within the nvu bin directory or installed versions
41
+ */ function isInNvuDir(filePath) {
44
42
  try {
45
43
  var realPath = _fs.default.realpathSync(filePath);
46
- return realPath.indexOf(_path.default.join('.nvu', 'bin')) >= 0 || pathsEqual(_path.default.dirname(realPath), nvuBinDir);
44
+ // Check for .nvu/bin or .nvu/installed
45
+ return realPath.indexOf(_path.default.join('.nvu', 'bin')) >= 0 || realPath.indexOf(_path.default.join('.nvu', 'installed')) >= 0 || pathsEqual(_path.default.dirname(realPath), nvuBinDir) || pathsEqual(_path.default.dirname(realPath), nvuInstalledDir);
47
46
  } catch (_e) {
48
47
  return false;
49
48
  }
@@ -69,8 +68,8 @@ function resolveSystemBinary(name) {
69
68
  try {
70
69
  var stat = _fs.default.statSync(candidate);
71
70
  if (!stat.isFile()) continue;
72
- // Make sure it's not in ~/.nvu/bin (via symlink)
73
- if (isInNvuBin(candidate)) continue;
71
+ // Make sure it's not in ~/.nvu/bin or ~/.nvu/installed/*/bin
72
+ if (isInNvuDir(candidate)) continue;
74
73
  return candidate;
75
74
  } catch (_e) {
76
75
  // File doesn't exist, continue
@@ -88,6 +87,7 @@ function getPathWithoutNvuBin() {
88
87
  if (!dir) continue;
89
88
  if (pathsEqual(dir, nvuBinDir)) continue;
90
89
  if (dir.indexOf(_path.default.join('.nvu', 'bin')) >= 0) continue;
90
+ if (dir.indexOf(_path.default.join('.nvu', 'installed')) >= 0) continue;
91
91
  filtered.push(dir);
92
92
  }
93
93
  return filtered.join(pathDelimiter);
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node-version/node-version-use/src/lib/resolveSystemBinary.ts"],"sourcesContent":["/**\n * Resolve system binaries by searching PATH while excluding ~/.nvu/bin\n * This mirrors the Go binary's findSystemBinary() function\n */\nimport envPathKey from 'env-path-key';\nimport fs from 'fs';\nimport path from 'path';\nimport { homedir } from '../compat.ts';\n\nconst isWindows = process.platform === 'win32' || /^(msys|cygwin)$/.test(process.env.OSTYPE);\nconst nvuBinDir = path.join(homedir(), '.nvu', 'bin');\nconst pathKey = envPathKey(); // PATH or Path or similar\nconst pathDelimiter = path.delimiter ? path.delimiter : isWindows ? ';' : ':';\n\n/**\n * Check if two paths are equal (case-insensitive on Windows)\n */\nfunction pathsEqual(a: string, b: string): boolean {\n if (isWindows) return a.toLowerCase() === b.toLowerCase();\n return a === b;\n}\n\n/**\n * Check if a path is within the nvu bin directory\n */\nfunction isInNvuBin(filePath: string): boolean {\n try {\n const realPath = fs.realpathSync(filePath);\n return realPath.indexOf(path.join('.nvu', 'bin')) >= 0 || pathsEqual(path.dirname(realPath), nvuBinDir);\n } catch (_e) {\n return false;\n }\n}\n\n/**\n * Find a system binary by searching PATH, excluding ~/.nvu/bin\n * Returns the full path to the binary, or null if not found\n */\nexport function resolveSystemBinary(name: string): string | null {\n const pathEnv = process.env[pathKey] || '';\n const dirs = pathEnv.split(pathDelimiter);\n\n for (let i = 0; i < dirs.length; i++) {\n const dir = dirs[i];\n if (!dir) continue;\n\n // Skip ~/.nvu/bin\n if (pathsEqual(dir, nvuBinDir)) continue;\n\n // Build candidate path with appropriate extension\n const candidates = isWindows ? [path.join(dir, `${name}.exe`), path.join(dir, `${name}.cmd`), path.join(dir, name)] : [path.join(dir, name)];\n\n for (let j = 0; j < candidates.length; j++) {\n const candidate = candidates[j];\n try {\n const stat = fs.statSync(candidate);\n if (!stat.isFile()) continue;\n\n // Make sure it's not in ~/.nvu/bin (via symlink)\n if (isInNvuBin(candidate)) continue;\n\n return candidate;\n } catch (_e) {\n // File doesn't exist, continue\n }\n }\n }\n\n return null;\n}\n\n/**\n * Get PATH with ~/.nvu/bin removed\n * Used to create an environment for spawning system commands\n */\nexport function getPathWithoutNvuBin(): string {\n const pathEnv = process.env[pathKey] || '';\n const dirs = pathEnv.split(pathDelimiter);\n\n const filtered: string[] = [];\n for (let i = 0; i < dirs.length; i++) {\n const dir = dirs[i];\n if (!dir) continue;\n if (pathsEqual(dir, nvuBinDir)) continue;\n if (dir.indexOf(path.join('.nvu', 'bin')) >= 0) continue;\n filtered.push(dir);\n }\n\n return filtered.join(pathDelimiter);\n}\n"],"names":["getPathWithoutNvuBin","resolveSystemBinary","isWindows","process","platform","test","env","OSTYPE","nvuBinDir","path","join","homedir","pathKey","envPathKey","pathDelimiter","delimiter","pathsEqual","a","b","toLowerCase","isInNvuBin","filePath","realPath","fs","realpathSync","indexOf","dirname","_e","name","pathEnv","dirs","split","i","length","dir","candidates","j","candidate","stat","statSync","isFile","filtered","push"],"mappings":"AAAA;;;CAGC;;;;;;;;;;;QAwEeA;eAAAA;;QArCAC;eAAAA;;;iEAlCO;yDACR;2DACE;wBACO;;;;;;AAExB,IAAMC,YAAYC,QAAQC,QAAQ,KAAK,WAAW,kBAAkBC,IAAI,CAACF,QAAQG,GAAG,CAACC,MAAM;AAC3F,IAAMC,YAAYC,aAAI,CAACC,IAAI,CAACC,IAAAA,iBAAO,KAAI,QAAQ;AAC/C,IAAMC,UAAUC,IAAAA,mBAAU,KAAI,0BAA0B;AACxD,IAAMC,gBAAgBL,aAAI,CAACM,SAAS,GAAGN,aAAI,CAACM,SAAS,GAAGb,YAAY,MAAM;AAE1E;;CAEC,GACD,SAASc,WAAWC,CAAS,EAAEC,CAAS;IACtC,IAAIhB,WAAW,OAAOe,EAAEE,WAAW,OAAOD,EAAEC,WAAW;IACvD,OAAOF,MAAMC;AACf;AAEA;;CAEC,GACD,SAASE,WAAWC,QAAgB;IAClC,IAAI;QACF,IAAMC,WAAWC,WAAE,CAACC,YAAY,CAACH;QACjC,OAAOC,SAASG,OAAO,CAAChB,aAAI,CAACC,IAAI,CAAC,QAAQ,WAAW,KAAKM,WAAWP,aAAI,CAACiB,OAAO,CAACJ,WAAWd;IAC/F,EAAE,OAAOmB,IAAI;QACX,OAAO;IACT;AACF;AAMO,SAAS1B,oBAAoB2B,IAAY;IAC9C,IAAMC,UAAU1B,QAAQG,GAAG,CAACM,QAAQ,IAAI;IACxC,IAAMkB,OAAOD,QAAQE,KAAK,CAACjB;IAE3B,IAAK,IAAIkB,IAAI,GAAGA,IAAIF,KAAKG,MAAM,EAAED,IAAK;QACpC,IAAME,MAAMJ,IAAI,CAACE,EAAE;QACnB,IAAI,CAACE,KAAK;QAEV,kBAAkB;QAClB,IAAIlB,WAAWkB,KAAK1B,YAAY;QAEhC,kDAAkD;QAClD,IAAM2B,aAAajC,YAAY;YAACO,aAAI,CAACC,IAAI,CAACwB,KAAK,AAAC,GAAO,OAALN,MAAK;YAAQnB,aAAI,CAACC,IAAI,CAACwB,KAAK,AAAC,GAAO,OAALN,MAAK;YAAQnB,aAAI,CAACC,IAAI,CAACwB,KAAKN;SAAM,GAAG;YAACnB,aAAI,CAACC,IAAI,CAACwB,KAAKN;SAAM;QAE5I,IAAK,IAAIQ,IAAI,GAAGA,IAAID,WAAWF,MAAM,EAAEG,IAAK;YAC1C,IAAMC,YAAYF,UAAU,CAACC,EAAE;YAC/B,IAAI;gBACF,IAAME,OAAOf,WAAE,CAACgB,QAAQ,CAACF;gBACzB,IAAI,CAACC,KAAKE,MAAM,IAAI;gBAEpB,iDAAiD;gBACjD,IAAIpB,WAAWiB,YAAY;gBAE3B,OAAOA;YACT,EAAE,OAAOV,IAAI;YACX,+BAA+B;YACjC;QACF;IACF;IAEA,OAAO;AACT;AAMO,SAAS3B;IACd,IAAM6B,UAAU1B,QAAQG,GAAG,CAACM,QAAQ,IAAI;IACxC,IAAMkB,OAAOD,QAAQE,KAAK,CAACjB;IAE3B,IAAM2B,WAAqB,EAAE;IAC7B,IAAK,IAAIT,IAAI,GAAGA,IAAIF,KAAKG,MAAM,EAAED,IAAK;QACpC,IAAME,MAAMJ,IAAI,CAACE,EAAE;QACnB,IAAI,CAACE,KAAK;QACV,IAAIlB,WAAWkB,KAAK1B,YAAY;QAChC,IAAI0B,IAAIT,OAAO,CAAChB,aAAI,CAACC,IAAI,CAAC,QAAQ,WAAW,GAAG;QAChD+B,SAASC,IAAI,CAACR;IAChB;IAEA,OAAOO,SAAS/B,IAAI,CAACI;AACvB"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node-version/node-version-use/src/lib/resolveSystemBinary.ts"],"sourcesContent":["import envPathKey from 'env-path-key';\nimport fs from 'fs';\nimport path from 'path';\nimport { homedir } from '../compat.ts';\n\nconst isWindows = process.platform === 'win32' || /^(msys|cygwin)$/.test(process.env.OSTYPE);\nconst nvuBinDir = path.join(homedir(), '.nvu', 'bin');\nconst nvuInstalledDir = path.join(homedir(), '.nvu', 'installed');\nconst pathKey = envPathKey(); // PATH or Path or similar\nconst pathDelimiter = path.delimiter ? path.delimiter : isWindows ? ';' : ':';\n\n/**\n * Check if two paths are equal (case-insensitive on Windows)\n */\nfunction pathsEqual(a: string, b: string): boolean {\n if (isWindows) return a.toLowerCase() === b.toLowerCase();\n return a === b;\n}\n\n/**\n * Check if a path is within the nvu bin directory or installed versions\n */\nfunction isInNvuDir(filePath: string): boolean {\n try {\n const realPath = fs.realpathSync(filePath);\n // Check for .nvu/bin or .nvu/installed\n return realPath.indexOf(path.join('.nvu', 'bin')) >= 0 || realPath.indexOf(path.join('.nvu', 'installed')) >= 0 || pathsEqual(path.dirname(realPath), nvuBinDir) || pathsEqual(path.dirname(realPath), nvuInstalledDir);\n } catch (_e) {\n return false;\n }\n}\n\n/**\n * Find a system binary by searching PATH, excluding ~/.nvu/bin and version directories\n * Returns the full path to the binary, or null if not found\n * NOTE: Keep in sync with Node.js resolveSystemBinary\n */\nexport function resolveSystemBinary(name: string): string | null {\n const pathEnv = process.env[pathKey] || '';\n const dirs = pathEnv.split(pathDelimiter);\n\n for (let i = 0; i < dirs.length; i++) {\n const dir = dirs[i];\n if (!dir) continue;\n\n // Skip ~/.nvu/bin\n if (pathsEqual(dir, nvuBinDir)) continue;\n\n // Build candidate path with appropriate extension\n const candidates = isWindows ? [path.join(dir, `${name}.exe`), path.join(dir, `${name}.cmd`), path.join(dir, name)] : [path.join(dir, name)];\n\n for (let j = 0; j < candidates.length; j++) {\n const candidate = candidates[j];\n try {\n const stat = fs.statSync(candidate);\n if (!stat.isFile()) continue;\n\n // Make sure it's not in ~/.nvu/bin or ~/.nvu/installed/*/bin\n if (isInNvuDir(candidate)) continue;\n\n return candidate;\n } catch (_e) {\n // File doesn't exist, continue\n }\n }\n }\n\n return null;\n}\n\n/**\n * Get PATH with ~/.nvu/bin and version directories removed\n * Used to create an environment for spawning system commands\n */\nexport function getPathWithoutNvuBin(): string {\n const pathEnv = process.env[pathKey] || '';\n const dirs = pathEnv.split(pathDelimiter);\n\n const filtered: string[] = [];\n for (let i = 0; i < dirs.length; i++) {\n const dir = dirs[i];\n if (!dir) continue;\n if (pathsEqual(dir, nvuBinDir)) continue;\n if (dir.indexOf(path.join('.nvu', 'bin')) >= 0) continue;\n if (dir.indexOf(path.join('.nvu', 'installed')) >= 0) continue;\n filtered.push(dir);\n }\n\n return filtered.join(pathDelimiter);\n}\n"],"names":["getPathWithoutNvuBin","resolveSystemBinary","isWindows","process","platform","test","env","OSTYPE","nvuBinDir","path","join","homedir","nvuInstalledDir","pathKey","envPathKey","pathDelimiter","delimiter","pathsEqual","a","b","toLowerCase","isInNvuDir","filePath","realPath","fs","realpathSync","indexOf","dirname","_e","name","pathEnv","dirs","split","i","length","dir","candidates","j","candidate","stat","statSync","isFile","filtered","push"],"mappings":"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"}
@@ -104,15 +104,16 @@ function worker(versionExpression, command, args, options, callback) {
104
104
  var queue = new _queuecb.default(1);
105
105
  // Create session once for all processes (only if multiple versions)
106
106
  var interactive = options.interactive !== false;
107
- var session = versions.length >= 2 && _spawnterm.createSession && !streamingOptions.streaming ? (0, _spawnterm.createSession)({
107
+ var session = versions.length >= 2 && process.stdout.isTTY && _spawnterm.createSession && !streamingOptions.streaming ? (0, _spawnterm.createSession)({
108
108
  header: "".concat(command, " ").concat(args.join(' ')),
109
109
  showStatusBar: true,
110
110
  interactive: interactive
111
111
  }) : null;
112
112
  versions.forEach(function(version) {
113
- queue.defer(function(cb) {
114
- installVersion(version, installOptions, function(err, installs) {
113
+ return queue.defer(function(cb) {
114
+ return installVersion(version, installOptions, function(err, installs) {
115
115
  var next = function next(err, res) {
116
+ if (!session && !options.silent) console.log('==============');
116
117
  if (err && err.message.indexOf('ExperimentalWarning') >= 0) {
117
118
  res = err;
118
119
  err = null;
@@ -142,19 +143,19 @@ function worker(versionExpression, command, args, options, callback) {
142
143
  var prefix = install.version;
143
144
  // On Windows, resolve npm bin commands to bypass .cmd wrappers
144
145
  var resolved = resolveCommand(command, args);
145
- if (versions.length < 2) {
146
- // Show command when running single version (no terminal session, unless silent)
147
- if (!options.silent) console.log("$ ".concat((0, _spawnterm.formatArguments)([
148
- resolved.command
149
- ].concat(resolved.args)).join(' ')));
150
- return (0, _crossspawncb.default)(resolved.command, resolved.args, spawnOptions, next);
151
- }
152
- if (session) session.spawn(resolved.command, resolved.args, spawnOptions, {
146
+ // Show command when running single version (no terminal session, unless silent)
147
+ if (!session && !options.silent) console.log(version);
148
+ if (!session && !options.silent) console.log('--------------');
149
+ if (!session && !options.silent) console.log("$ ".concat((0, _spawnterm.formatArguments)([
150
+ resolved.command
151
+ ].concat(resolved.args)).join(' ')));
152
+ if (versions.length < 2) (0, _crossspawncb.default)(resolved.command, resolved.args, spawnOptions, next);
153
+ else if (session) session.spawn(resolved.command, resolved.args, spawnOptions, {
153
154
  group: prefix,
154
155
  expanded: streamingOptions.expanded
155
156
  }, next);
156
157
  else (0, _spawnstreaming.default)(resolved.command, resolved.args, spawnOptions, {
157
- prefix: prefix
158
+ prefix: process.stdout.isTTY ? prefix : undefined
158
159
  }, next);
159
160
  });
160
161
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node-version/node-version-use/src/worker.ts"],"sourcesContent":["import spawn, { type SpawnOptions } from 'cross-spawn-cb';\nimport fs from 'fs';\nimport resolveVersions, { type VersionOptions } from 'node-resolve-versions';\nimport type { InstallOptions } from 'node-version-install';\nimport { spawnOptions as createSpawnOptions } from 'node-version-utils';\nimport path from 'path';\nimport Queue from 'queue-cb';\nimport resolveBin from 'resolve-bin-sync';\nimport spawnStreaming from 'spawn-streaming';\nimport { createSession, formatArguments } from 'spawn-term';\nimport { objectAssign, stringEndsWith } from './compat.ts';\nimport { storagePath } from './constants.ts';\nimport loadNodeVersionInstall from './lib/loadNodeVersionInstall.ts';\nimport { getPathWithoutNvuBin, resolveSystemBinary } from './lib/resolveSystemBinary.ts';\n\nimport type { Options, UseCallback, UseOptions, UseResult } from './types.ts';\n\nconst isWindows = process.platform === 'win32' || /^(msys|cygwin)$/.test(process.env.OSTYPE);\nconst NODE = isWindows ? 'node.exe' : 'node';\n\n// Parse npm-generated .cmd wrapper to extract the JS script path\nfunction parseNpmCmdWrapper(cmdPath: string): string | null {\n try {\n const content = fs.readFileSync(cmdPath, 'utf8');\n // Match: \"%_prog%\" \"%dp0%\\node_modules\\...\\cli.js\" %*\n // or: \"%_prog%\" \"%dp0%\\path\\to\\script.js\" %*\n const match = content.match(/\"%_prog%\"\\s+\"?%dp0%\\\\([^\"]+)\"?\\s+%\\*/);\n if (match) {\n const relativePath = match[1];\n const cmdDir = path.dirname(cmdPath);\n return path.join(cmdDir, relativePath);\n }\n } catch (_e) {\n // ignore\n }\n return null;\n}\n\n// On Windows, resolve npm bin commands to their JS entry points to bypass .cmd wrappers\n// This fixes issues with nvm-windows where .cmd wrappers use symlinked node.exe directly\nfunction resolveCommand(command: string, args: string[]): { command: string; args: string[] } {\n if (!isWindows) return { command, args };\n\n // Case 1: Command is a .cmd file path\n if (stringEndsWith(command.toLowerCase(), '.cmd')) {\n const scriptPath = parseNpmCmdWrapper(command);\n if (scriptPath) {\n return { command: NODE, args: [scriptPath].concat(args) };\n }\n }\n\n // Case 2: Try to resolve the command as an npm package bin from node_modules\n try {\n const binPath = resolveBin(command);\n return { command: NODE, args: [binPath].concat(args) };\n } catch (_e) {\n // Not an npm package bin, use original command\n }\n\n return { command, args };\n}\n\nexport default function worker(versionExpression: string, command: string, args: string[], options: UseOptions, callback: UseCallback): void {\n // Handle \"system\" as a special version that uses system binaries directly\n if (versionExpression === 'system') {\n runWithSystemBinaries(command, args, options, callback);\n return;\n }\n\n // Load node-version-install lazily\n loadNodeVersionInstall((loadErr, installVersion) => {\n if (loadErr) return callback(loadErr);\n\n resolveVersions(versionExpression, options as VersionOptions, (err?: Error, versions?: string[]) => {\n if (err) return callback(err);\n if (!versions.length) {\n callback(new Error(`No versions found from expression: ${versionExpression}`));\n return;\n }\n\n const installOptions = objectAssign({ storagePath: storagePath }, options) as InstallOptions;\n const streamingOptions = options as Options;\n const results: UseResult[] = [];\n const queue = new Queue(1);\n\n // Create session once for all processes (only if multiple versions)\n const interactive = options.interactive !== false;\n const session = versions.length >= 2 && createSession && !streamingOptions.streaming ? createSession({ header: `${command} ${args.join(' ')}`, showStatusBar: true, interactive }) : null;\n\n versions.forEach((version: string) => {\n queue.defer((cb) => {\n installVersion(version, installOptions, (err, installs) => {\n const install = installs && installs.length === 1 ? installs[0] : null;\n if (err || !install) {\n const error = err || new Error(`Unexpected version results for version ${version}. Install ${JSON.stringify(installs)}`);\n results.push({ install, command, version, error, result: null });\n return cb();\n }\n const spawnOptions = createSpawnOptions(install.installPath, options as SpawnOptions);\n const prefix = install.version;\n\n function next(err?, res?): void {\n if (err && err.message.indexOf('ExperimentalWarning') >= 0) {\n res = err;\n err = null;\n }\n results.push({ install, command, version, error: err, result: res });\n cb();\n }\n\n // On Windows, resolve npm bin commands to bypass .cmd wrappers\n const resolved = resolveCommand(command, args);\n\n if (versions.length < 2) {\n // Show command when running single version (no terminal session, unless silent)\n if (!options.silent) console.log(`$ ${formatArguments([resolved.command].concat(resolved.args)).join(' ')}`);\n return spawn(resolved.command, resolved.args, spawnOptions, next);\n }\n if (session) session.spawn(resolved.command, resolved.args, spawnOptions, { group: prefix, expanded: streamingOptions.expanded }, next);\n else spawnStreaming(resolved.command, resolved.args, spawnOptions, { prefix }, next);\n });\n });\n });\n queue.await((err) => {\n if (session) {\n session.waitAndClose(() => {\n err ? callback(err) : callback(null, results);\n });\n } else {\n err ? callback(err) : callback(null, results);\n }\n });\n });\n });\n}\n\n/**\n * Run command using system binaries (bypassing nvu version management)\n * This handles the \"system\" version specifier\n */\nfunction runWithSystemBinaries(command: string, args: string[], options: UseOptions, callback: UseCallback): void {\n // Find the system binary for the command\n const systemBinary = resolveSystemBinary(command);\n if (!systemBinary) {\n callback(new Error(`System ${command} not found in PATH`));\n return;\n }\n\n // Create spawn options with PATH excluding ~/.nvu/bin\n // This ensures any child processes also use system binaries\n const cleanPath = getPathWithoutNvuBin();\n const spawnOptions: SpawnOptions = objectAssign({}, options as SpawnOptions);\n spawnOptions.env = objectAssign({}, process.env);\n spawnOptions.env.PATH = cleanPath;\n spawnOptions.stdio = options.stdio || 'inherit';\n\n // On Windows, resolve npm bin commands to bypass .cmd wrappers\n const resolved = resolveCommand(command, args);\n\n // For system, use the resolved system binary path\n const finalCommand = resolved.command === command ? systemBinary : resolved.command;\n const finalArgs = resolved.command === command ? args : resolved.args;\n\n if (!options.silent) {\n console.log(`$ ${formatArguments([finalCommand].concat(finalArgs)).join(' ')}`);\n }\n\n spawn(finalCommand, finalArgs, spawnOptions, (err?, res?) => {\n if (err && err.message && err.message.indexOf('ExperimentalWarning') >= 0) {\n res = err;\n err = null;\n }\n\n const result: UseResult = {\n install: null,\n command,\n version: 'system',\n error: err,\n result: res,\n };\n\n callback(err, [result]);\n });\n}\n"],"names":["worker","isWindows","process","platform","test","env","OSTYPE","NODE","parseNpmCmdWrapper","cmdPath","content","fs","readFileSync","match","relativePath","cmdDir","path","dirname","join","_e","resolveCommand","command","args","stringEndsWith","toLowerCase","scriptPath","concat","binPath","resolveBin","versionExpression","options","callback","runWithSystemBinaries","loadNodeVersionInstall","loadErr","installVersion","resolveVersions","err","versions","length","Error","installOptions","objectAssign","storagePath","streamingOptions","results","queue","Queue","interactive","session","createSession","streaming","header","showStatusBar","forEach","version","defer","cb","installs","next","res","message","indexOf","push","install","error","result","JSON","stringify","spawnOptions","createSpawnOptions","installPath","prefix","resolved","silent","console","log","formatArguments","spawn","group","expanded","spawnStreaming","await","waitAndClose","systemBinary","resolveSystemBinary","cleanPath","getPathWithoutNvuBin","PATH","stdio","finalCommand","finalArgs"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node-version/node-version-use/src/worker.ts"],"sourcesContent":["import spawn, { type SpawnOptions } from 'cross-spawn-cb';\nimport fs from 'fs';\nimport resolveVersions, { type VersionOptions } from 'node-resolve-versions';\nimport type { InstallOptions } from 'node-version-install';\nimport { spawnOptions as createSpawnOptions } from 'node-version-utils';\nimport path from 'path';\nimport Queue from 'queue-cb';\nimport resolveBin from 'resolve-bin-sync';\nimport spawnStreaming from 'spawn-streaming';\nimport { createSession, formatArguments } from 'spawn-term';\nimport { objectAssign, stringEndsWith } from './compat.ts';\nimport { storagePath } from './constants.ts';\nimport loadNodeVersionInstall from './lib/loadNodeVersionInstall.ts';\nimport { getPathWithoutNvuBin, resolveSystemBinary } from './lib/resolveSystemBinary.ts';\n\nimport type { Options, UseCallback, UseOptions, UseResult } from './types.ts';\n\nconst isWindows = process.platform === 'win32' || /^(msys|cygwin)$/.test(process.env.OSTYPE);\nconst NODE = isWindows ? 'node.exe' : 'node';\n\n// Parse npm-generated .cmd wrapper to extract the JS script path\nfunction parseNpmCmdWrapper(cmdPath: string): string | null {\n try {\n const content = fs.readFileSync(cmdPath, 'utf8');\n // Match: \"%_prog%\" \"%dp0%\\node_modules\\...\\cli.js\" %*\n // or: \"%_prog%\" \"%dp0%\\path\\to\\script.js\" %*\n const match = content.match(/\"%_prog%\"\\s+\"?%dp0%\\\\([^\"]+)\"?\\s+%\\*/);\n if (match) {\n const relativePath = match[1];\n const cmdDir = path.dirname(cmdPath);\n return path.join(cmdDir, relativePath);\n }\n } catch (_e) {\n // ignore\n }\n return null;\n}\n\n// On Windows, resolve npm bin commands to their JS entry points to bypass .cmd wrappers\n// This fixes issues with nvm-windows where .cmd wrappers use symlinked node.exe directly\nfunction resolveCommand(command: string, args: string[]): { command: string; args: string[] } {\n if (!isWindows) return { command, args };\n\n // Case 1: Command is a .cmd file path\n if (stringEndsWith(command.toLowerCase(), '.cmd')) {\n const scriptPath = parseNpmCmdWrapper(command);\n if (scriptPath) {\n return { command: NODE, args: [scriptPath].concat(args) };\n }\n }\n\n // Case 2: Try to resolve the command as an npm package bin from node_modules\n try {\n const binPath = resolveBin(command);\n return { command: NODE, args: [binPath].concat(args) };\n } catch (_e) {\n // Not an npm package bin, use original command\n }\n\n return { command, args };\n}\n\nexport default function worker(versionExpression: string, command: string, args: string[], options: UseOptions, callback: UseCallback): void {\n // Handle \"system\" as a special version that uses system binaries directly\n if (versionExpression === 'system') {\n runWithSystemBinaries(command, args, options, callback);\n return;\n }\n\n // Load node-version-install lazily\n loadNodeVersionInstall((loadErr, installVersion) => {\n if (loadErr) return callback(loadErr);\n\n resolveVersions(versionExpression, options as VersionOptions, (err?: Error, versions?: string[]) => {\n if (err) return callback(err);\n if (!versions.length) {\n callback(new Error(`No versions found from expression: ${versionExpression}`));\n return;\n }\n\n const installOptions = objectAssign({ storagePath: storagePath }, options) as InstallOptions;\n const streamingOptions = options as Options;\n const results: UseResult[] = [];\n const queue = new Queue(1);\n\n // Create session once for all processes (only if multiple versions)\n const interactive = options.interactive !== false;\n const session = versions.length >= 2 && process.stdout.isTTY && createSession && !streamingOptions.streaming ? createSession({ header: `${command} ${args.join(' ')}`, showStatusBar: true, interactive }) : null;\n\n versions.forEach((version: string) =>\n queue.defer((cb) =>\n installVersion(version, installOptions, (err, installs) => {\n const install = installs && installs.length === 1 ? installs[0] : null;\n if (err || !install) {\n const error = err || new Error(`Unexpected version results for version ${version}. Install ${JSON.stringify(installs)}`);\n results.push({ install, command, version, error, result: null });\n return cb();\n }\n const spawnOptions = createSpawnOptions(install.installPath, options as SpawnOptions);\n const prefix = install.version;\n\n function next(err?, res?): void {\n if (!session && !options.silent) console.log('==============');\n if (err && err.message.indexOf('ExperimentalWarning') >= 0) {\n res = err;\n err = null;\n }\n results.push({ install, command, version, error: err, result: res });\n cb();\n }\n\n // On Windows, resolve npm bin commands to bypass .cmd wrappers\n const resolved = resolveCommand(command, args);\n\n // Show command when running single version (no terminal session, unless silent)\n if (!session && !options.silent) console.log(version);\n if (!session && !options.silent) console.log('--------------');\n if (!session && !options.silent) console.log(`$ ${formatArguments([resolved.command].concat(resolved.args)).join(' ')}`);\n\n if (versions.length < 2) spawn(resolved.command, resolved.args, spawnOptions, next);\n else if (session) session.spawn(resolved.command, resolved.args, spawnOptions, { group: prefix, expanded: streamingOptions.expanded }, next);\n else spawnStreaming(resolved.command, resolved.args, spawnOptions, { prefix: process.stdout.isTTY ? prefix : undefined }, next);\n })\n )\n );\n queue.await((err) => {\n if (session) {\n session.waitAndClose(() => {\n err ? callback(err) : callback(null, results);\n });\n } else {\n err ? callback(err) : callback(null, results);\n }\n });\n });\n });\n}\n\n/**\n * Run command using system binaries (bypassing nvu version management)\n * This handles the \"system\" version specifier\n */\nfunction runWithSystemBinaries(command: string, args: string[], options: UseOptions, callback: UseCallback): void {\n // Find the system binary for the command\n const systemBinary = resolveSystemBinary(command);\n if (!systemBinary) {\n callback(new Error(`System ${command} not found in PATH`));\n return;\n }\n\n // Create spawn options with PATH excluding ~/.nvu/bin\n // This ensures any child processes also use system binaries\n const cleanPath = getPathWithoutNvuBin();\n const spawnOptions: SpawnOptions = objectAssign({}, options as SpawnOptions);\n spawnOptions.env = objectAssign({}, process.env);\n spawnOptions.env.PATH = cleanPath;\n spawnOptions.stdio = options.stdio || 'inherit';\n\n // On Windows, resolve npm bin commands to bypass .cmd wrappers\n const resolved = resolveCommand(command, args);\n\n // For system, use the resolved system binary path\n const finalCommand = resolved.command === command ? systemBinary : resolved.command;\n const finalArgs = resolved.command === command ? args : resolved.args;\n\n if (!options.silent) {\n console.log(`$ ${formatArguments([finalCommand].concat(finalArgs)).join(' ')}`);\n }\n\n spawn(finalCommand, finalArgs, spawnOptions, (err?, res?) => {\n if (err && err.message && err.message.indexOf('ExperimentalWarning') >= 0) {\n res = err;\n err = null;\n }\n\n const result: UseResult = {\n install: null,\n command,\n version: 'system',\n error: err,\n result: res,\n };\n\n callback(err, [result]);\n });\n}\n"],"names":["worker","isWindows","process","platform","test","env","OSTYPE","NODE","parseNpmCmdWrapper","cmdPath","content","fs","readFileSync","match","relativePath","cmdDir","path","dirname","join","_e","resolveCommand","command","args","stringEndsWith","toLowerCase","scriptPath","concat","binPath","resolveBin","versionExpression","options","callback","runWithSystemBinaries","loadNodeVersionInstall","loadErr","installVersion","resolveVersions","err","versions","length","Error","installOptions","objectAssign","storagePath","streamingOptions","results","queue","Queue","interactive","session","stdout","isTTY","createSession","streaming","header","showStatusBar","forEach","version","defer","cb","installs","next","res","silent","console","log","message","indexOf","push","install","error","result","JSON","stringify","spawnOptions","createSpawnOptions","installPath","prefix","resolved","formatArguments","spawn","group","expanded","spawnStreaming","undefined","await","waitAndClose","systemBinary","resolveSystemBinary","cleanPath","getPathWithoutNvuBin","PATH","stdio","finalCommand","finalArgs"],"mappings":"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"}
@@ -3,6 +3,7 @@ import fs from 'fs';
3
3
  import path from 'path';
4
4
  import { readdirWithTypes } from '../compat.js';
5
5
  import { storagePath } from '../constants.js';
6
+ import compareVersions from '../lib/compareVersions.js';
6
7
  /**
7
8
  * nvu list
8
9
  *
@@ -31,18 +32,8 @@ import { storagePath } from '../constants.js';
31
32
  if (fs.existsSync(defaultFilePath)) {
32
33
  defaultVersion = fs.readFileSync(defaultFilePath, 'utf8').trim();
33
34
  }
34
- // Sort versions (simple string sort, could be improved with semver)
35
- versions.sort((a, b)=>{
36
- const aParts = a.split('.').map((n)=>parseInt(n, 10) || 0);
37
- const bParts = b.split('.').map((n)=>parseInt(n, 10) || 0);
38
- for(let i = 0; i < Math.max(aParts.length, bParts.length); i++){
39
- const aVal = aParts[i] || 0;
40
- const bVal = bParts[i] || 0;
41
- if (aVal !== bVal) return bVal - aVal; // Descending order
42
- }
43
- return 0;
44
- });
45
35
  console.log('Installed Node versions:');
36
+ versions.sort(compareVersions);
46
37
  for(let i = 0; i < versions.length; i++){
47
38
  const version = versions[i];
48
39
  const isDefault = version === defaultVersion || `v${version}` === defaultVersion || version === `v${defaultVersion}`;
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node-version/node-version-use/src/commands/list.ts"],"sourcesContent":["import exit from 'exit-compat';\nimport fs from 'fs';\nimport path from 'path';\nimport { readdirWithTypes } from '../compat.ts';\nimport { storagePath } from '../constants.ts';\n\n/**\n * nvu list\n *\n * List all installed Node versions.\n */\nexport default function listCmd(_args: string[]): void {\n const versionsPath = path.join(storagePath, 'installed');\n\n // Check if versions directory exists\n if (!fs.existsSync(versionsPath)) {\n console.log('No Node versions installed.');\n console.log('Install a version: nvu install <version>');\n exit(0);\n return;\n }\n\n // Read all directories in versions folder\n const entries = readdirWithTypes(versionsPath);\n const versions = entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);\n\n if (versions.length === 0) {\n console.log('No Node versions installed.');\n console.log('Install a version: nvu install <version>');\n exit(0);\n return;\n }\n\n // Get the current default\n const defaultFilePath = path.join(storagePath, 'default');\n let defaultVersion = '';\n if (fs.existsSync(defaultFilePath)) {\n defaultVersion = fs.readFileSync(defaultFilePath, 'utf8').trim();\n }\n\n // Sort versions (simple string sort, could be improved with semver)\n versions.sort((a, b) => {\n const aParts = a.split('.').map((n) => parseInt(n, 10) || 0);\n const bParts = b.split('.').map((n) => parseInt(n, 10) || 0);\n for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {\n const aVal = aParts[i] || 0;\n const bVal = bParts[i] || 0;\n if (aVal !== bVal) return bVal - aVal; // Descending order\n }\n return 0;\n });\n\n console.log('Installed Node versions:');\n for (let i = 0; i < versions.length; i++) {\n const version = versions[i];\n const isDefault = version === defaultVersion || `v${version}` === defaultVersion || version === `v${defaultVersion}`;\n const marker = isDefault ? ' (default)' : '';\n console.log(` ${version}${marker}`);\n }\n exit(0);\n}\n"],"names":["exit","fs","path","readdirWithTypes","storagePath","listCmd","_args","versionsPath","join","existsSync","console","log","entries","versions","filter","entry","isDirectory","map","name","length","defaultFilePath","defaultVersion","readFileSync","trim","sort","a","b","aParts","split","n","parseInt","bParts","i","Math","max","aVal","bVal","version","isDefault","marker"],"mappings":"AAAA,OAAOA,UAAU,cAAc;AAC/B,OAAOC,QAAQ,KAAK;AACpB,OAAOC,UAAU,OAAO;AACxB,SAASC,gBAAgB,QAAQ,eAAe;AAChD,SAASC,WAAW,QAAQ,kBAAkB;AAE9C;;;;CAIC,GACD,eAAe,SAASC,QAAQC,KAAe;IAC7C,MAAMC,eAAeL,KAAKM,IAAI,CAACJ,aAAa;IAE5C,qCAAqC;IACrC,IAAI,CAACH,GAAGQ,UAAU,CAACF,eAAe;QAChCG,QAAQC,GAAG,CAAC;QACZD,QAAQC,GAAG,CAAC;QACZX,KAAK;QACL;IACF;IAEA,0CAA0C;IAC1C,MAAMY,UAAUT,iBAAiBI;IACjC,MAAMM,WAAWD,QAAQE,MAAM,CAAC,CAACC,QAAUA,MAAMC,WAAW,IAAIC,GAAG,CAAC,CAACF,QAAUA,MAAMG,IAAI;IAEzF,IAAIL,SAASM,MAAM,KAAK,GAAG;QACzBT,QAAQC,GAAG,CAAC;QACZD,QAAQC,GAAG,CAAC;QACZX,KAAK;QACL;IACF;IAEA,0BAA0B;IAC1B,MAAMoB,kBAAkBlB,KAAKM,IAAI,CAACJ,aAAa;IAC/C,IAAIiB,iBAAiB;IACrB,IAAIpB,GAAGQ,UAAU,CAACW,kBAAkB;QAClCC,iBAAiBpB,GAAGqB,YAAY,CAACF,iBAAiB,QAAQG,IAAI;IAChE;IAEA,oEAAoE;IACpEV,SAASW,IAAI,CAAC,CAACC,GAAGC;QAChB,MAAMC,SAASF,EAAEG,KAAK,CAAC,KAAKX,GAAG,CAAC,CAACY,IAAMC,SAASD,GAAG,OAAO;QAC1D,MAAME,SAASL,EAAEE,KAAK,CAAC,KAAKX,GAAG,CAAC,CAACY,IAAMC,SAASD,GAAG,OAAO;QAC1D,IAAK,IAAIG,IAAI,GAAGA,IAAIC,KAAKC,GAAG,CAACP,OAAOR,MAAM,EAAEY,OAAOZ,MAAM,GAAGa,IAAK;YAC/D,MAAMG,OAAOR,MAAM,CAACK,EAAE,IAAI;YAC1B,MAAMI,OAAOL,MAAM,CAACC,EAAE,IAAI;YAC1B,IAAIG,SAASC,MAAM,OAAOA,OAAOD,MAAM,mBAAmB;QAC5D;QACA,OAAO;IACT;IAEAzB,QAAQC,GAAG,CAAC;IACZ,IAAK,IAAIqB,IAAI,GAAGA,IAAInB,SAASM,MAAM,EAAEa,IAAK;QACxC,MAAMK,UAAUxB,QAAQ,CAACmB,EAAE;QAC3B,MAAMM,YAAYD,YAAYhB,kBAAkB,CAAC,CAAC,EAAEgB,SAAS,KAAKhB,kBAAkBgB,YAAY,CAAC,CAAC,EAAEhB,gBAAgB;QACpH,MAAMkB,SAASD,YAAY,eAAe;QAC1C5B,QAAQC,GAAG,CAAC,CAAC,EAAE,EAAE0B,UAAUE,QAAQ;IACrC;IACAvC,KAAK;AACP"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node-version/node-version-use/src/commands/list.ts"],"sourcesContent":["import exit from 'exit-compat';\nimport fs from 'fs';\nimport path from 'path';\nimport { readdirWithTypes } from '../compat.ts';\nimport { storagePath } from '../constants.ts';\nimport compareVersions from '../lib/compareVersions.ts';\n\n/**\n * nvu list\n *\n * List all installed Node versions.\n */\nexport default function listCmd(_args: string[]): void {\n const versionsPath = path.join(storagePath, 'installed');\n\n // Check if versions directory exists\n if (!fs.existsSync(versionsPath)) {\n console.log('No Node versions installed.');\n console.log('Install a version: nvu install <version>');\n exit(0);\n return;\n }\n\n // Read all directories in versions folder\n const entries = readdirWithTypes(versionsPath);\n const versions = entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);\n\n if (versions.length === 0) {\n console.log('No Node versions installed.');\n console.log('Install a version: nvu install <version>');\n exit(0);\n return;\n }\n\n // Get the current default\n const defaultFilePath = path.join(storagePath, 'default');\n let defaultVersion = '';\n if (fs.existsSync(defaultFilePath)) {\n defaultVersion = fs.readFileSync(defaultFilePath, 'utf8').trim();\n }\n\n console.log('Installed Node versions:');\n versions.sort(compareVersions);\n for (let i = 0; i < versions.length; i++) {\n const version = versions[i];\n const isDefault = version === defaultVersion || `v${version}` === defaultVersion || version === `v${defaultVersion}`;\n const marker = isDefault ? ' (default)' : '';\n console.log(` ${version}${marker}`);\n }\n exit(0);\n}\n"],"names":["exit","fs","path","readdirWithTypes","storagePath","compareVersions","listCmd","_args","versionsPath","join","existsSync","console","log","entries","versions","filter","entry","isDirectory","map","name","length","defaultFilePath","defaultVersion","readFileSync","trim","sort","i","version","isDefault","marker"],"mappings":"AAAA,OAAOA,UAAU,cAAc;AAC/B,OAAOC,QAAQ,KAAK;AACpB,OAAOC,UAAU,OAAO;AACxB,SAASC,gBAAgB,QAAQ,eAAe;AAChD,SAASC,WAAW,QAAQ,kBAAkB;AAC9C,OAAOC,qBAAqB,4BAA4B;AAExD;;;;CAIC,GACD,eAAe,SAASC,QAAQC,KAAe;IAC7C,MAAMC,eAAeN,KAAKO,IAAI,CAACL,aAAa;IAE5C,qCAAqC;IACrC,IAAI,CAACH,GAAGS,UAAU,CAACF,eAAe;QAChCG,QAAQC,GAAG,CAAC;QACZD,QAAQC,GAAG,CAAC;QACZZ,KAAK;QACL;IACF;IAEA,0CAA0C;IAC1C,MAAMa,UAAUV,iBAAiBK;IACjC,MAAMM,WAAWD,QAAQE,MAAM,CAAC,CAACC,QAAUA,MAAMC,WAAW,IAAIC,GAAG,CAAC,CAACF,QAAUA,MAAMG,IAAI;IAEzF,IAAIL,SAASM,MAAM,KAAK,GAAG;QACzBT,QAAQC,GAAG,CAAC;QACZD,QAAQC,GAAG,CAAC;QACZZ,KAAK;QACL;IACF;IAEA,0BAA0B;IAC1B,MAAMqB,kBAAkBnB,KAAKO,IAAI,CAACL,aAAa;IAC/C,IAAIkB,iBAAiB;IACrB,IAAIrB,GAAGS,UAAU,CAACW,kBAAkB;QAClCC,iBAAiBrB,GAAGsB,YAAY,CAACF,iBAAiB,QAAQG,IAAI;IAChE;IAEAb,QAAQC,GAAG,CAAC;IACZE,SAASW,IAAI,CAACpB;IACd,IAAK,IAAIqB,IAAI,GAAGA,IAAIZ,SAASM,MAAM,EAAEM,IAAK;QACxC,MAAMC,UAAUb,QAAQ,CAACY,EAAE;QAC3B,MAAME,YAAYD,YAAYL,kBAAkB,CAAC,CAAC,EAAEK,SAAS,KAAKL,kBAAkBK,YAAY,CAAC,CAAC,EAAEL,gBAAgB;QACpH,MAAMO,SAASD,YAAY,eAAe;QAC1CjB,QAAQC,GAAG,CAAC,CAAC,EAAE,EAAEe,UAAUE,QAAQ;IACrC;IACA7B,KAAK;AACP"}
package/dist/esm/index.js CHANGED
@@ -3,7 +3,5 @@ export default function nodeVersionUse(versionExpression, command, args, options
3
3
  callback = typeof options === 'function' ? options : callback;
4
4
  options = typeof options === 'function' ? {} : options || {};
5
5
  if (typeof callback === 'function') return worker(versionExpression, command, args, options, callback);
6
- return new Promise((resolve, reject)=>worker(versionExpression, command, args, options, (err, result)=>{
7
- err ? reject(err) : resolve(result);
8
- }));
6
+ return new Promise((resolve, reject)=>worker(versionExpression, command, args, options, (err, result)=>err ? reject(err) : resolve(result)));
9
7
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node-version/node-version-use/src/index.ts"],"sourcesContent":["import type { UseCallback, UseOptions, UseResult } from './types.ts';\nimport worker from './worker.ts';\n\nexport type * from './types.ts';\n\nexport default function nodeVersionUse(versionExpression: string, command: string, args: string[]): Promise<UseResult[]>;\nexport default function nodeVersionUse(versionExpression: string, command: string, args: string[], options: UseOptions): Promise<UseResult[]>;\n\nexport default function nodeVersionUse(versionExpression: string, command: string, args: string[], callback: UseCallback): void;\nexport default function nodeVersionUse(versionExpression: string, command: string, args: string[], options: UseOptions, callback: UseCallback): void;\n\nexport default function nodeVersionUse(versionExpression: string, command: string, args: string[], options?: UseOptions | UseCallback, callback?: UseCallback): void | Promise<UseResult[]> {\n callback = typeof options === 'function' ? options : callback;\n options = typeof options === 'function' ? {} : ((options || {}) as UseOptions);\n\n if (typeof callback === 'function') return worker(versionExpression, command, args, options, callback);\n return new Promise((resolve, reject) =>\n worker(versionExpression, command, args, options, (err, result) => {\n err ? reject(err) : resolve(result);\n })\n );\n}\n"],"names":["worker","nodeVersionUse","versionExpression","command","args","options","callback","Promise","resolve","reject","err","result"],"mappings":"AACA,OAAOA,YAAY,cAAc;AAUjC,eAAe,SAASC,eAAeC,iBAAyB,EAAEC,OAAe,EAAEC,IAAc,EAAEC,OAAkC,EAAEC,QAAsB;IAC3JA,WAAW,OAAOD,YAAY,aAAaA,UAAUC;IACrDD,UAAU,OAAOA,YAAY,aAAa,CAAC,IAAMA,WAAW,CAAC;IAE7D,IAAI,OAAOC,aAAa,YAAY,OAAON,OAAOE,mBAAmBC,SAASC,MAAMC,SAASC;IAC7F,OAAO,IAAIC,QAAQ,CAACC,SAASC,SAC3BT,OAAOE,mBAAmBC,SAASC,MAAMC,SAAS,CAACK,KAAKC;YACtDD,MAAMD,OAAOC,OAAOF,QAAQG;QAC9B;AAEJ"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node-version/node-version-use/src/index.ts"],"sourcesContent":["import type { UseCallback, UseOptions, UseResult } from './types.ts';\nimport worker from './worker.ts';\n\nexport type * from './types.ts';\n\nexport default function nodeVersionUse(versionExpression: string, command: string, args: string[]): Promise<UseResult[]>;\nexport default function nodeVersionUse(versionExpression: string, command: string, args: string[], options: UseOptions): Promise<UseResult[]>;\n\nexport default function nodeVersionUse(versionExpression: string, command: string, args: string[], callback: UseCallback): void;\nexport default function nodeVersionUse(versionExpression: string, command: string, args: string[], options: UseOptions, callback: UseCallback): void;\n\nexport default function nodeVersionUse(versionExpression: string, command: string, args: string[], options?: UseOptions | UseCallback, callback?: UseCallback): void | Promise<UseResult[]> {\n callback = typeof options === 'function' ? options : callback;\n options = typeof options === 'function' ? {} : ((options || {}) as UseOptions);\n\n if (typeof callback === 'function') return worker(versionExpression, command, args, options, callback);\n return new Promise((resolve, reject) => worker(versionExpression, command, args, options, (err, result) => (err ? reject(err) : resolve(result))));\n}\n"],"names":["worker","nodeVersionUse","versionExpression","command","args","options","callback","Promise","resolve","reject","err","result"],"mappings":"AACA,OAAOA,YAAY,cAAc;AAUjC,eAAe,SAASC,eAAeC,iBAAyB,EAAEC,OAAe,EAAEC,IAAc,EAAEC,OAAkC,EAAEC,QAAsB;IAC3JA,WAAW,OAAOD,YAAY,aAAaA,UAAUC;IACrDD,UAAU,OAAOA,YAAY,aAAa,CAAC,IAAMA,WAAW,CAAC;IAE7D,IAAI,OAAOC,aAAa,YAAY,OAAON,OAAOE,mBAAmBC,SAASC,MAAMC,SAASC;IAC7F,OAAO,IAAIC,QAAQ,CAACC,SAASC,SAAWT,OAAOE,mBAAmBC,SAASC,MAAMC,SAAS,CAACK,KAAKC,SAAYD,MAAMD,OAAOC,OAAOF,QAAQG;AAC1I"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Compare two semver version strings (e.g., "20.19.0" vs "20.9.1")
3
+ * Returns: negative if a < b, positive if a > b, 0 if equal
4
+ */
5
+ export default function compareVersions(a: string, b: string): number;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Compare two semver version strings (e.g., "20.19.0" vs "20.9.1")
3
+ * Returns: negative if a < b, positive if a > b, 0 if equal
4
+ */ export default function compareVersions(a, b) {
5
+ const aParts = a.replace(/^v/, '').split('.');
6
+ const bParts = b.replace(/^v/, '').split('.');
7
+ const len = Math.max(aParts.length, bParts.length);
8
+ for(let i = 0; i < len; i++){
9
+ const aNum = parseInt(aParts[i], 10) || 0;
10
+ const bNum = parseInt(bParts[i], 10) || 0;
11
+ if (aNum !== bNum) return aNum - bNum;
12
+ }
13
+ return 0;
14
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node-version/node-version-use/src/lib/compareVersions.ts"],"sourcesContent":["/**\n * Compare two semver version strings (e.g., \"20.19.0\" vs \"20.9.1\")\n * Returns: negative if a < b, positive if a > b, 0 if equal\n */\nexport default function compareVersions(a: string, b: string): number {\n const aParts = a.replace(/^v/, '').split('.');\n const bParts = b.replace(/^v/, '').split('.');\n const len = Math.max(aParts.length, bParts.length);\n\n for (let i = 0; i < len; i++) {\n const aNum = parseInt(aParts[i], 10) || 0;\n const bNum = parseInt(bParts[i], 10) || 0;\n if (aNum !== bNum) return aNum - bNum;\n }\n return 0;\n}\n"],"names":["compareVersions","a","b","aParts","replace","split","bParts","len","Math","max","length","i","aNum","parseInt","bNum"],"mappings":"AAAA;;;CAGC,GACD,eAAe,SAASA,gBAAgBC,CAAS,EAAEC,CAAS;IAC1D,MAAMC,SAASF,EAAEG,OAAO,CAAC,MAAM,IAAIC,KAAK,CAAC;IACzC,MAAMC,SAASJ,EAAEE,OAAO,CAAC,MAAM,IAAIC,KAAK,CAAC;IACzC,MAAME,MAAMC,KAAKC,GAAG,CAACN,OAAOO,MAAM,EAAEJ,OAAOI,MAAM;IAEjD,IAAK,IAAIC,IAAI,GAAGA,IAAIJ,KAAKI,IAAK;QAC5B,MAAMC,OAAOC,SAASV,MAAM,CAACQ,EAAE,EAAE,OAAO;QACxC,MAAMG,OAAOD,SAASP,MAAM,CAACK,EAAE,EAAE,OAAO;QACxC,IAAIC,SAASE,MAAM,OAAOF,OAAOE;IACnC;IACA,OAAO;AACT"}
@@ -1,22 +1,7 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
3
  import { readdirWithTypes } from '../compat.js';
4
- /**
5
- * Compare two semver version strings (e.g., "20.19.0" vs "20.9.1")
6
- * Returns: negative if a < b, positive if a > b, 0 if equal
7
- */ function compareVersions(a, b) {
8
- const aParts = a.replace(/^v/, '').split('.');
9
- const bParts = b.replace(/^v/, '').split('.');
10
- const len = Math.max(aParts.length, bParts.length);
11
- for(let i = 0; i < len; i++){
12
- const aNum = parseInt(aParts[i], 10) || 0;
13
- const bNum = parseInt(bParts[i], 10) || 0;
14
- if (aNum !== bNum) {
15
- return aNum - bNum;
16
- }
17
- }
18
- return 0;
19
- }
4
+ import compareVersions from './compareVersions.js';
20
5
  /**
21
6
  * Find all installed versions matching the given version string
22
7
  * Results are sorted in ascending semver order (lowest first, highest last)
@@ -56,8 +41,7 @@ import { readdirWithTypes } from '../compat.js';
56
41
  }
57
42
  }
58
43
  // Sort by semver (ascending) so highest version is last
59
- matches.sort(compareVersions);
60
- return matches;
44
+ return matches.sort(compareVersions);
61
45
  }
62
46
  /**
63
47
  * Get all installed versions
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node-version/node-version-use/src/lib/findInstalledVersions.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\nimport { readdirWithTypes } from '../compat.ts';\n\n/**\n * Compare two semver version strings (e.g., \"20.19.0\" vs \"20.9.1\")\n * Returns: negative if a < b, positive if a > b, 0 if equal\n */\nfunction compareVersions(a: string, b: string): number {\n const aParts = a.replace(/^v/, '').split('.');\n const bParts = b.replace(/^v/, '').split('.');\n const len = Math.max(aParts.length, bParts.length);\n\n for (let i = 0; i < len; i++) {\n const aNum = parseInt(aParts[i], 10) || 0;\n const bNum = parseInt(bParts[i], 10) || 0;\n if (aNum !== bNum) {\n return aNum - bNum;\n }\n }\n return 0;\n}\n\n/**\n * Find all installed versions matching the given version string\n * Results are sorted in ascending semver order (lowest first, highest last)\n */\nexport function findInstalledVersions(versionsPath: string, version: string): string[] {\n if (!fs.existsSync(versionsPath)) {\n return [];\n }\n\n const normalizedVersion = version.replace(/^v/, '');\n const matches: string[] = [];\n\n // Try exact matches first\n const exactMatches = [version, `v${normalizedVersion}`, normalizedVersion];\n for (let i = 0; i < exactMatches.length; i++) {\n const v = exactMatches[i];\n const versionPath = path.join(versionsPath, v);\n if (fs.existsSync(versionPath) && fs.statSync(versionPath).isDirectory()) {\n if (matches.indexOf(v) === -1) {\n matches.push(v);\n }\n }\n }\n\n // If we have an exact match, return just that\n if (matches.length > 0) {\n return matches;\n }\n\n // Try partial match (e.g., \"20\" matches \"v20.19.6\")\n const entries = readdirWithTypes(versionsPath);\n for (let j = 0; j < entries.length; j++) {\n const entry = entries[j];\n if (!entry.isDirectory()) continue;\n const dirVersion = entry.name.replace(/^v/, '');\n if (dirVersion.indexOf(`${normalizedVersion}.`) === 0) {\n matches.push(entry.name);\n }\n }\n\n // Sort by semver (ascending) so highest version is last\n matches.sort(compareVersions);\n\n return matches;\n}\n\n/**\n * Get all installed versions\n */\nexport function getAllInstalledVersions(versionsPath: string): string[] {\n if (!fs.existsSync(versionsPath)) {\n return [];\n }\n\n const entries = readdirWithTypes(versionsPath);\n const versions: string[] = [];\n for (let i = 0; i < entries.length; i++) {\n if (entries[i].isDirectory()) {\n versions.push(entries[i].name);\n }\n }\n\n return versions;\n}\n"],"names":["fs","path","readdirWithTypes","compareVersions","a","b","aParts","replace","split","bParts","len","Math","max","length","i","aNum","parseInt","bNum","findInstalledVersions","versionsPath","version","existsSync","normalizedVersion","matches","exactMatches","v","versionPath","join","statSync","isDirectory","indexOf","push","entries","j","entry","dirVersion","name","sort","getAllInstalledVersions","versions"],"mappings":"AAAA,OAAOA,QAAQ,KAAK;AACpB,OAAOC,UAAU,OAAO;AACxB,SAASC,gBAAgB,QAAQ,eAAe;AAEhD;;;CAGC,GACD,SAASC,gBAAgBC,CAAS,EAAEC,CAAS;IAC3C,MAAMC,SAASF,EAAEG,OAAO,CAAC,MAAM,IAAIC,KAAK,CAAC;IACzC,MAAMC,SAASJ,EAAEE,OAAO,CAAC,MAAM,IAAIC,KAAK,CAAC;IACzC,MAAME,MAAMC,KAAKC,GAAG,CAACN,OAAOO,MAAM,EAAEJ,OAAOI,MAAM;IAEjD,IAAK,IAAIC,IAAI,GAAGA,IAAIJ,KAAKI,IAAK;QAC5B,MAAMC,OAAOC,SAASV,MAAM,CAACQ,EAAE,EAAE,OAAO;QACxC,MAAMG,OAAOD,SAASP,MAAM,CAACK,EAAE,EAAE,OAAO;QACxC,IAAIC,SAASE,MAAM;YACjB,OAAOF,OAAOE;QAChB;IACF;IACA,OAAO;AACT;AAEA;;;CAGC,GACD,OAAO,SAASC,sBAAsBC,YAAoB,EAAEC,OAAe;IACzE,IAAI,CAACpB,GAAGqB,UAAU,CAACF,eAAe;QAChC,OAAO,EAAE;IACX;IAEA,MAAMG,oBAAoBF,QAAQb,OAAO,CAAC,MAAM;IAChD,MAAMgB,UAAoB,EAAE;IAE5B,0BAA0B;IAC1B,MAAMC,eAAe;QAACJ;QAAS,CAAC,CAAC,EAAEE,mBAAmB;QAAEA;KAAkB;IAC1E,IAAK,IAAIR,IAAI,GAAGA,IAAIU,aAAaX,MAAM,EAAEC,IAAK;QAC5C,MAAMW,IAAID,YAAY,CAACV,EAAE;QACzB,MAAMY,cAAczB,KAAK0B,IAAI,CAACR,cAAcM;QAC5C,IAAIzB,GAAGqB,UAAU,CAACK,gBAAgB1B,GAAG4B,QAAQ,CAACF,aAAaG,WAAW,IAAI;YACxE,IAAIN,QAAQO,OAAO,CAACL,OAAO,CAAC,GAAG;gBAC7BF,QAAQQ,IAAI,CAACN;YACf;QACF;IACF;IAEA,8CAA8C;IAC9C,IAAIF,QAAQV,MAAM,GAAG,GAAG;QACtB,OAAOU;IACT;IAEA,oDAAoD;IACpD,MAAMS,UAAU9B,iBAAiBiB;IACjC,IAAK,IAAIc,IAAI,GAAGA,IAAID,QAAQnB,MAAM,EAAEoB,IAAK;QACvC,MAAMC,QAAQF,OAAO,CAACC,EAAE;QACxB,IAAI,CAACC,MAAML,WAAW,IAAI;QAC1B,MAAMM,aAAaD,MAAME,IAAI,CAAC7B,OAAO,CAAC,MAAM;QAC5C,IAAI4B,WAAWL,OAAO,CAAC,GAAGR,kBAAkB,CAAC,CAAC,MAAM,GAAG;YACrDC,QAAQQ,IAAI,CAACG,MAAME,IAAI;QACzB;IACF;IAEA,wDAAwD;IACxDb,QAAQc,IAAI,CAAClC;IAEb,OAAOoB;AACT;AAEA;;CAEC,GACD,OAAO,SAASe,wBAAwBnB,YAAoB;IAC1D,IAAI,CAACnB,GAAGqB,UAAU,CAACF,eAAe;QAChC,OAAO,EAAE;IACX;IAEA,MAAMa,UAAU9B,iBAAiBiB;IACjC,MAAMoB,WAAqB,EAAE;IAC7B,IAAK,IAAIzB,IAAI,GAAGA,IAAIkB,QAAQnB,MAAM,EAAEC,IAAK;QACvC,IAAIkB,OAAO,CAAClB,EAAE,CAACe,WAAW,IAAI;YAC5BU,SAASR,IAAI,CAACC,OAAO,CAAClB,EAAE,CAACsB,IAAI;QAC/B;IACF;IAEA,OAAOG;AACT"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node-version/node-version-use/src/lib/findInstalledVersions.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\nimport { readdirWithTypes } from '../compat.ts';\nimport compareVersions from './compareVersions.ts';\n\n/**\n * Find all installed versions matching the given version string\n * Results are sorted in ascending semver order (lowest first, highest last)\n */\nexport function findInstalledVersions(versionsPath: string, version: string): string[] {\n if (!fs.existsSync(versionsPath)) {\n return [];\n }\n\n const normalizedVersion = version.replace(/^v/, '');\n const matches: string[] = [];\n\n // Try exact matches first\n const exactMatches = [version, `v${normalizedVersion}`, normalizedVersion];\n for (let i = 0; i < exactMatches.length; i++) {\n const v = exactMatches[i];\n const versionPath = path.join(versionsPath, v);\n if (fs.existsSync(versionPath) && fs.statSync(versionPath).isDirectory()) {\n if (matches.indexOf(v) === -1) {\n matches.push(v);\n }\n }\n }\n\n // If we have an exact match, return just that\n if (matches.length > 0) {\n return matches;\n }\n\n // Try partial match (e.g., \"20\" matches \"v20.19.6\")\n const entries = readdirWithTypes(versionsPath);\n for (let j = 0; j < entries.length; j++) {\n const entry = entries[j];\n if (!entry.isDirectory()) continue;\n const dirVersion = entry.name.replace(/^v/, '');\n if (dirVersion.indexOf(`${normalizedVersion}.`) === 0) {\n matches.push(entry.name);\n }\n }\n\n // Sort by semver (ascending) so highest version is last\n return matches.sort(compareVersions);\n}\n\n/**\n * Get all installed versions\n */\nexport function getAllInstalledVersions(versionsPath: string): string[] {\n if (!fs.existsSync(versionsPath)) {\n return [];\n }\n\n const entries = readdirWithTypes(versionsPath);\n const versions: string[] = [];\n for (let i = 0; i < entries.length; i++) {\n if (entries[i].isDirectory()) {\n versions.push(entries[i].name);\n }\n }\n\n return versions;\n}\n"],"names":["fs","path","readdirWithTypes","compareVersions","findInstalledVersions","versionsPath","version","existsSync","normalizedVersion","replace","matches","exactMatches","i","length","v","versionPath","join","statSync","isDirectory","indexOf","push","entries","j","entry","dirVersion","name","sort","getAllInstalledVersions","versions"],"mappings":"AAAA,OAAOA,QAAQ,KAAK;AACpB,OAAOC,UAAU,OAAO;AACxB,SAASC,gBAAgB,QAAQ,eAAe;AAChD,OAAOC,qBAAqB,uBAAuB;AAEnD;;;CAGC,GACD,OAAO,SAASC,sBAAsBC,YAAoB,EAAEC,OAAe;IACzE,IAAI,CAACN,GAAGO,UAAU,CAACF,eAAe;QAChC,OAAO,EAAE;IACX;IAEA,MAAMG,oBAAoBF,QAAQG,OAAO,CAAC,MAAM;IAChD,MAAMC,UAAoB,EAAE;IAE5B,0BAA0B;IAC1B,MAAMC,eAAe;QAACL;QAAS,CAAC,CAAC,EAAEE,mBAAmB;QAAEA;KAAkB;IAC1E,IAAK,IAAII,IAAI,GAAGA,IAAID,aAAaE,MAAM,EAAED,IAAK;QAC5C,MAAME,IAAIH,YAAY,CAACC,EAAE;QACzB,MAAMG,cAAcd,KAAKe,IAAI,CAACX,cAAcS;QAC5C,IAAId,GAAGO,UAAU,CAACQ,gBAAgBf,GAAGiB,QAAQ,CAACF,aAAaG,WAAW,IAAI;YACxE,IAAIR,QAAQS,OAAO,CAACL,OAAO,CAAC,GAAG;gBAC7BJ,QAAQU,IAAI,CAACN;YACf;QACF;IACF;IAEA,8CAA8C;IAC9C,IAAIJ,QAAQG,MAAM,GAAG,GAAG;QACtB,OAAOH;IACT;IAEA,oDAAoD;IACpD,MAAMW,UAAUnB,iBAAiBG;IACjC,IAAK,IAAIiB,IAAI,GAAGA,IAAID,QAAQR,MAAM,EAAES,IAAK;QACvC,MAAMC,QAAQF,OAAO,CAACC,EAAE;QACxB,IAAI,CAACC,MAAML,WAAW,IAAI;QAC1B,MAAMM,aAAaD,MAAME,IAAI,CAAChB,OAAO,CAAC,MAAM;QAC5C,IAAIe,WAAWL,OAAO,CAAC,GAAGX,kBAAkB,CAAC,CAAC,MAAM,GAAG;YACrDE,QAAQU,IAAI,CAACG,MAAME,IAAI;QACzB;IACF;IAEA,wDAAwD;IACxD,OAAOf,QAAQgB,IAAI,CAACvB;AACtB;AAEA;;CAEC,GACD,OAAO,SAASwB,wBAAwBtB,YAAoB;IAC1D,IAAI,CAACL,GAAGO,UAAU,CAACF,eAAe;QAChC,OAAO,EAAE;IACX;IAEA,MAAMgB,UAAUnB,iBAAiBG;IACjC,MAAMuB,WAAqB,EAAE;IAC7B,IAAK,IAAIhB,IAAI,GAAGA,IAAIS,QAAQR,MAAM,EAAED,IAAK;QACvC,IAAIS,OAAO,CAACT,EAAE,CAACM,WAAW,IAAI;YAC5BU,SAASR,IAAI,CAACC,OAAO,CAACT,EAAE,CAACa,IAAI;QAC/B;IACF;IAEA,OAAOG;AACT"}
@@ -1,10 +1,11 @@
1
1
  /**
2
- * Find a system binary by searching PATH, excluding ~/.nvu/bin
2
+ * Find a system binary by searching PATH, excluding ~/.nvu/bin and version directories
3
3
  * Returns the full path to the binary, or null if not found
4
+ * NOTE: Keep in sync with Node.js resolveSystemBinary
4
5
  */
5
6
  export declare function resolveSystemBinary(name: string): string | null;
6
7
  /**
7
- * Get PATH with ~/.nvu/bin removed
8
+ * Get PATH with ~/.nvu/bin and version directories removed
8
9
  * Used to create an environment for spawning system commands
9
10
  */
10
11
  export declare function getPathWithoutNvuBin(): string;
@@ -1,12 +1,10 @@
1
- /**
2
- * Resolve system binaries by searching PATH while excluding ~/.nvu/bin
3
- * This mirrors the Go binary's findSystemBinary() function
4
- */ import envPathKey from 'env-path-key';
1
+ import envPathKey from 'env-path-key';
5
2
  import fs from 'fs';
6
3
  import path from 'path';
7
4
  import { homedir } from '../compat.js';
8
5
  const isWindows = process.platform === 'win32' || /^(msys|cygwin)$/.test(process.env.OSTYPE);
9
6
  const nvuBinDir = path.join(homedir(), '.nvu', 'bin');
7
+ const nvuInstalledDir = path.join(homedir(), '.nvu', 'installed');
10
8
  const pathKey = envPathKey(); // PATH or Path or similar
11
9
  const pathDelimiter = path.delimiter ? path.delimiter : isWindows ? ';' : ':';
12
10
  /**
@@ -16,18 +14,20 @@ const pathDelimiter = path.delimiter ? path.delimiter : isWindows ? ';' : ':';
16
14
  return a === b;
17
15
  }
18
16
  /**
19
- * Check if a path is within the nvu bin directory
20
- */ function isInNvuBin(filePath) {
17
+ * Check if a path is within the nvu bin directory or installed versions
18
+ */ function isInNvuDir(filePath) {
21
19
  try {
22
20
  const realPath = fs.realpathSync(filePath);
23
- return realPath.indexOf(path.join('.nvu', 'bin')) >= 0 || pathsEqual(path.dirname(realPath), nvuBinDir);
21
+ // Check for .nvu/bin or .nvu/installed
22
+ return realPath.indexOf(path.join('.nvu', 'bin')) >= 0 || realPath.indexOf(path.join('.nvu', 'installed')) >= 0 || pathsEqual(path.dirname(realPath), nvuBinDir) || pathsEqual(path.dirname(realPath), nvuInstalledDir);
24
23
  } catch (_e) {
25
24
  return false;
26
25
  }
27
26
  }
28
27
  /**
29
- * Find a system binary by searching PATH, excluding ~/.nvu/bin
28
+ * Find a system binary by searching PATH, excluding ~/.nvu/bin and version directories
30
29
  * Returns the full path to the binary, or null if not found
30
+ * NOTE: Keep in sync with Node.js resolveSystemBinary
31
31
  */ export function resolveSystemBinary(name) {
32
32
  const pathEnv = process.env[pathKey] || '';
33
33
  const dirs = pathEnv.split(pathDelimiter);
@@ -49,8 +49,8 @@ const pathDelimiter = path.delimiter ? path.delimiter : isWindows ? ';' : ':';
49
49
  try {
50
50
  const stat = fs.statSync(candidate);
51
51
  if (!stat.isFile()) continue;
52
- // Make sure it's not in ~/.nvu/bin (via symlink)
53
- if (isInNvuBin(candidate)) continue;
52
+ // Make sure it's not in ~/.nvu/bin or ~/.nvu/installed/*/bin
53
+ if (isInNvuDir(candidate)) continue;
54
54
  return candidate;
55
55
  } catch (_e) {
56
56
  // File doesn't exist, continue
@@ -60,7 +60,7 @@ const pathDelimiter = path.delimiter ? path.delimiter : isWindows ? ';' : ':';
60
60
  return null;
61
61
  }
62
62
  /**
63
- * Get PATH with ~/.nvu/bin removed
63
+ * Get PATH with ~/.nvu/bin and version directories removed
64
64
  * Used to create an environment for spawning system commands
65
65
  */ export function getPathWithoutNvuBin() {
66
66
  const pathEnv = process.env[pathKey] || '';
@@ -71,6 +71,7 @@ const pathDelimiter = path.delimiter ? path.delimiter : isWindows ? ';' : ':';
71
71
  if (!dir) continue;
72
72
  if (pathsEqual(dir, nvuBinDir)) continue;
73
73
  if (dir.indexOf(path.join('.nvu', 'bin')) >= 0) continue;
74
+ if (dir.indexOf(path.join('.nvu', 'installed')) >= 0) continue;
74
75
  filtered.push(dir);
75
76
  }
76
77
  return filtered.join(pathDelimiter);
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node-version/node-version-use/src/lib/resolveSystemBinary.ts"],"sourcesContent":["/**\n * Resolve system binaries by searching PATH while excluding ~/.nvu/bin\n * This mirrors the Go binary's findSystemBinary() function\n */\nimport envPathKey from 'env-path-key';\nimport fs from 'fs';\nimport path from 'path';\nimport { homedir } from '../compat.ts';\n\nconst isWindows = process.platform === 'win32' || /^(msys|cygwin)$/.test(process.env.OSTYPE);\nconst nvuBinDir = path.join(homedir(), '.nvu', 'bin');\nconst pathKey = envPathKey(); // PATH or Path or similar\nconst pathDelimiter = path.delimiter ? path.delimiter : isWindows ? ';' : ':';\n\n/**\n * Check if two paths are equal (case-insensitive on Windows)\n */\nfunction pathsEqual(a: string, b: string): boolean {\n if (isWindows) return a.toLowerCase() === b.toLowerCase();\n return a === b;\n}\n\n/**\n * Check if a path is within the nvu bin directory\n */\nfunction isInNvuBin(filePath: string): boolean {\n try {\n const realPath = fs.realpathSync(filePath);\n return realPath.indexOf(path.join('.nvu', 'bin')) >= 0 || pathsEqual(path.dirname(realPath), nvuBinDir);\n } catch (_e) {\n return false;\n }\n}\n\n/**\n * Find a system binary by searching PATH, excluding ~/.nvu/bin\n * Returns the full path to the binary, or null if not found\n */\nexport function resolveSystemBinary(name: string): string | null {\n const pathEnv = process.env[pathKey] || '';\n const dirs = pathEnv.split(pathDelimiter);\n\n for (let i = 0; i < dirs.length; i++) {\n const dir = dirs[i];\n if (!dir) continue;\n\n // Skip ~/.nvu/bin\n if (pathsEqual(dir, nvuBinDir)) continue;\n\n // Build candidate path with appropriate extension\n const candidates = isWindows ? [path.join(dir, `${name}.exe`), path.join(dir, `${name}.cmd`), path.join(dir, name)] : [path.join(dir, name)];\n\n for (let j = 0; j < candidates.length; j++) {\n const candidate = candidates[j];\n try {\n const stat = fs.statSync(candidate);\n if (!stat.isFile()) continue;\n\n // Make sure it's not in ~/.nvu/bin (via symlink)\n if (isInNvuBin(candidate)) continue;\n\n return candidate;\n } catch (_e) {\n // File doesn't exist, continue\n }\n }\n }\n\n return null;\n}\n\n/**\n * Get PATH with ~/.nvu/bin removed\n * Used to create an environment for spawning system commands\n */\nexport function getPathWithoutNvuBin(): string {\n const pathEnv = process.env[pathKey] || '';\n const dirs = pathEnv.split(pathDelimiter);\n\n const filtered: string[] = [];\n for (let i = 0; i < dirs.length; i++) {\n const dir = dirs[i];\n if (!dir) continue;\n if (pathsEqual(dir, nvuBinDir)) continue;\n if (dir.indexOf(path.join('.nvu', 'bin')) >= 0) continue;\n filtered.push(dir);\n }\n\n return filtered.join(pathDelimiter);\n}\n"],"names":["envPathKey","fs","path","homedir","isWindows","process","platform","test","env","OSTYPE","nvuBinDir","join","pathKey","pathDelimiter","delimiter","pathsEqual","a","b","toLowerCase","isInNvuBin","filePath","realPath","realpathSync","indexOf","dirname","_e","resolveSystemBinary","name","pathEnv","dirs","split","i","length","dir","candidates","j","candidate","stat","statSync","isFile","getPathWithoutNvuBin","filtered","push"],"mappings":"AAAA;;;CAGC,GACD,OAAOA,gBAAgB,eAAe;AACtC,OAAOC,QAAQ,KAAK;AACpB,OAAOC,UAAU,OAAO;AACxB,SAASC,OAAO,QAAQ,eAAe;AAEvC,MAAMC,YAAYC,QAAQC,QAAQ,KAAK,WAAW,kBAAkBC,IAAI,CAACF,QAAQG,GAAG,CAACC,MAAM;AAC3F,MAAMC,YAAYR,KAAKS,IAAI,CAACR,WAAW,QAAQ;AAC/C,MAAMS,UAAUZ,cAAc,0BAA0B;AACxD,MAAMa,gBAAgBX,KAAKY,SAAS,GAAGZ,KAAKY,SAAS,GAAGV,YAAY,MAAM;AAE1E;;CAEC,GACD,SAASW,WAAWC,CAAS,EAAEC,CAAS;IACtC,IAAIb,WAAW,OAAOY,EAAEE,WAAW,OAAOD,EAAEC,WAAW;IACvD,OAAOF,MAAMC;AACf;AAEA;;CAEC,GACD,SAASE,WAAWC,QAAgB;IAClC,IAAI;QACF,MAAMC,WAAWpB,GAAGqB,YAAY,CAACF;QACjC,OAAOC,SAASE,OAAO,CAACrB,KAAKS,IAAI,CAAC,QAAQ,WAAW,KAAKI,WAAWb,KAAKsB,OAAO,CAACH,WAAWX;IAC/F,EAAE,OAAOe,IAAI;QACX,OAAO;IACT;AACF;AAEA;;;CAGC,GACD,OAAO,SAASC,oBAAoBC,IAAY;IAC9C,MAAMC,UAAUvB,QAAQG,GAAG,CAACI,QAAQ,IAAI;IACxC,MAAMiB,OAAOD,QAAQE,KAAK,CAACjB;IAE3B,IAAK,IAAIkB,IAAI,GAAGA,IAAIF,KAAKG,MAAM,EAAED,IAAK;QACpC,MAAME,MAAMJ,IAAI,CAACE,EAAE;QACnB,IAAI,CAACE,KAAK;QAEV,kBAAkB;QAClB,IAAIlB,WAAWkB,KAAKvB,YAAY;QAEhC,kDAAkD;QAClD,MAAMwB,aAAa9B,YAAY;YAACF,KAAKS,IAAI,CAACsB,KAAK,GAAGN,KAAK,IAAI,CAAC;YAAGzB,KAAKS,IAAI,CAACsB,KAAK,GAAGN,KAAK,IAAI,CAAC;YAAGzB,KAAKS,IAAI,CAACsB,KAAKN;SAAM,GAAG;YAACzB,KAAKS,IAAI,CAACsB,KAAKN;SAAM;QAE5I,IAAK,IAAIQ,IAAI,GAAGA,IAAID,WAAWF,MAAM,EAAEG,IAAK;YAC1C,MAAMC,YAAYF,UAAU,CAACC,EAAE;YAC/B,IAAI;gBACF,MAAME,OAAOpC,GAAGqC,QAAQ,CAACF;gBACzB,IAAI,CAACC,KAAKE,MAAM,IAAI;gBAEpB,iDAAiD;gBACjD,IAAIpB,WAAWiB,YAAY;gBAE3B,OAAOA;YACT,EAAE,OAAOX,IAAI;YACX,+BAA+B;YACjC;QACF;IACF;IAEA,OAAO;AACT;AAEA;;;CAGC,GACD,OAAO,SAASe;IACd,MAAMZ,UAAUvB,QAAQG,GAAG,CAACI,QAAQ,IAAI;IACxC,MAAMiB,OAAOD,QAAQE,KAAK,CAACjB;IAE3B,MAAM4B,WAAqB,EAAE;IAC7B,IAAK,IAAIV,IAAI,GAAGA,IAAIF,KAAKG,MAAM,EAAED,IAAK;QACpC,MAAME,MAAMJ,IAAI,CAACE,EAAE;QACnB,IAAI,CAACE,KAAK;QACV,IAAIlB,WAAWkB,KAAKvB,YAAY;QAChC,IAAIuB,IAAIV,OAAO,CAACrB,KAAKS,IAAI,CAAC,QAAQ,WAAW,GAAG;QAChD8B,SAASC,IAAI,CAACT;IAChB;IAEA,OAAOQ,SAAS9B,IAAI,CAACE;AACvB"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node-version/node-version-use/src/lib/resolveSystemBinary.ts"],"sourcesContent":["import envPathKey from 'env-path-key';\nimport fs from 'fs';\nimport path from 'path';\nimport { homedir } from '../compat.ts';\n\nconst isWindows = process.platform === 'win32' || /^(msys|cygwin)$/.test(process.env.OSTYPE);\nconst nvuBinDir = path.join(homedir(), '.nvu', 'bin');\nconst nvuInstalledDir = path.join(homedir(), '.nvu', 'installed');\nconst pathKey = envPathKey(); // PATH or Path or similar\nconst pathDelimiter = path.delimiter ? path.delimiter : isWindows ? ';' : ':';\n\n/**\n * Check if two paths are equal (case-insensitive on Windows)\n */\nfunction pathsEqual(a: string, b: string): boolean {\n if (isWindows) return a.toLowerCase() === b.toLowerCase();\n return a === b;\n}\n\n/**\n * Check if a path is within the nvu bin directory or installed versions\n */\nfunction isInNvuDir(filePath: string): boolean {\n try {\n const realPath = fs.realpathSync(filePath);\n // Check for .nvu/bin or .nvu/installed\n return realPath.indexOf(path.join('.nvu', 'bin')) >= 0 || realPath.indexOf(path.join('.nvu', 'installed')) >= 0 || pathsEqual(path.dirname(realPath), nvuBinDir) || pathsEqual(path.dirname(realPath), nvuInstalledDir);\n } catch (_e) {\n return false;\n }\n}\n\n/**\n * Find a system binary by searching PATH, excluding ~/.nvu/bin and version directories\n * Returns the full path to the binary, or null if not found\n * NOTE: Keep in sync with Node.js resolveSystemBinary\n */\nexport function resolveSystemBinary(name: string): string | null {\n const pathEnv = process.env[pathKey] || '';\n const dirs = pathEnv.split(pathDelimiter);\n\n for (let i = 0; i < dirs.length; i++) {\n const dir = dirs[i];\n if (!dir) continue;\n\n // Skip ~/.nvu/bin\n if (pathsEqual(dir, nvuBinDir)) continue;\n\n // Build candidate path with appropriate extension\n const candidates = isWindows ? [path.join(dir, `${name}.exe`), path.join(dir, `${name}.cmd`), path.join(dir, name)] : [path.join(dir, name)];\n\n for (let j = 0; j < candidates.length; j++) {\n const candidate = candidates[j];\n try {\n const stat = fs.statSync(candidate);\n if (!stat.isFile()) continue;\n\n // Make sure it's not in ~/.nvu/bin or ~/.nvu/installed/*/bin\n if (isInNvuDir(candidate)) continue;\n\n return candidate;\n } catch (_e) {\n // File doesn't exist, continue\n }\n }\n }\n\n return null;\n}\n\n/**\n * Get PATH with ~/.nvu/bin and version directories removed\n * Used to create an environment for spawning system commands\n */\nexport function getPathWithoutNvuBin(): string {\n const pathEnv = process.env[pathKey] || '';\n const dirs = pathEnv.split(pathDelimiter);\n\n const filtered: string[] = [];\n for (let i = 0; i < dirs.length; i++) {\n const dir = dirs[i];\n if (!dir) continue;\n if (pathsEqual(dir, nvuBinDir)) continue;\n if (dir.indexOf(path.join('.nvu', 'bin')) >= 0) continue;\n if (dir.indexOf(path.join('.nvu', 'installed')) >= 0) continue;\n filtered.push(dir);\n }\n\n return filtered.join(pathDelimiter);\n}\n"],"names":["envPathKey","fs","path","homedir","isWindows","process","platform","test","env","OSTYPE","nvuBinDir","join","nvuInstalledDir","pathKey","pathDelimiter","delimiter","pathsEqual","a","b","toLowerCase","isInNvuDir","filePath","realPath","realpathSync","indexOf","dirname","_e","resolveSystemBinary","name","pathEnv","dirs","split","i","length","dir","candidates","j","candidate","stat","statSync","isFile","getPathWithoutNvuBin","filtered","push"],"mappings":"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"}
@@ -89,14 +89,12 @@ export default function worker(versionExpression, command, args, options, callba
89
89
  const queue = new Queue(1);
90
90
  // Create session once for all processes (only if multiple versions)
91
91
  const interactive = options.interactive !== false;
92
- const session = versions.length >= 2 && createSession && !streamingOptions.streaming ? createSession({
92
+ const session = versions.length >= 2 && process.stdout.isTTY && createSession && !streamingOptions.streaming ? createSession({
93
93
  header: `${command} ${args.join(' ')}`,
94
94
  showStatusBar: true,
95
95
  interactive
96
96
  }) : null;
97
- versions.forEach((version)=>{
98
- queue.defer((cb)=>{
99
- installVersion(version, installOptions, (err, installs)=>{
97
+ versions.forEach((version)=>queue.defer((cb)=>installVersion(version, installOptions, (err, installs)=>{
100
98
  const install = installs && installs.length === 1 ? installs[0] : null;
101
99
  if (err || !install) {
102
100
  const error = err || new Error(`Unexpected version results for version ${version}. Install ${JSON.stringify(installs)}`);
@@ -112,6 +110,7 @@ export default function worker(versionExpression, command, args, options, callba
112
110
  const spawnOptions = createSpawnOptions(install.installPath, options);
113
111
  const prefix = install.version;
114
112
  function next(err, res) {
113
+ if (!session && !options.silent) console.log('==============');
115
114
  if (err && err.message.indexOf('ExperimentalWarning') >= 0) {
116
115
  res = err;
117
116
  err = null;
@@ -127,23 +126,21 @@ export default function worker(versionExpression, command, args, options, callba
127
126
  }
128
127
  // On Windows, resolve npm bin commands to bypass .cmd wrappers
129
128
  const resolved = resolveCommand(command, args);
130
- if (versions.length < 2) {
131
- // Show command when running single version (no terminal session, unless silent)
132
- if (!options.silent) console.log(`$ ${formatArguments([
133
- resolved.command
134
- ].concat(resolved.args)).join(' ')}`);
135
- return spawn(resolved.command, resolved.args, spawnOptions, next);
136
- }
137
- if (session) session.spawn(resolved.command, resolved.args, spawnOptions, {
129
+ // Show command when running single version (no terminal session, unless silent)
130
+ if (!session && !options.silent) console.log(version);
131
+ if (!session && !options.silent) console.log('--------------');
132
+ if (!session && !options.silent) console.log(`$ ${formatArguments([
133
+ resolved.command
134
+ ].concat(resolved.args)).join(' ')}`);
135
+ if (versions.length < 2) spawn(resolved.command, resolved.args, spawnOptions, next);
136
+ else if (session) session.spawn(resolved.command, resolved.args, spawnOptions, {
138
137
  group: prefix,
139
138
  expanded: streamingOptions.expanded
140
139
  }, next);
141
140
  else spawnStreaming(resolved.command, resolved.args, spawnOptions, {
142
- prefix
141
+ prefix: process.stdout.isTTY ? prefix : undefined
143
142
  }, next);
144
- });
145
- });
146
- });
143
+ })));
147
144
  queue.await((err)=>{
148
145
  if (session) {
149
146
  session.waitAndClose(()=>{
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node-version/node-version-use/src/worker.ts"],"sourcesContent":["import spawn, { type SpawnOptions } from 'cross-spawn-cb';\nimport fs from 'fs';\nimport resolveVersions, { type VersionOptions } from 'node-resolve-versions';\nimport type { InstallOptions } from 'node-version-install';\nimport { spawnOptions as createSpawnOptions } from 'node-version-utils';\nimport path from 'path';\nimport Queue from 'queue-cb';\nimport resolveBin from 'resolve-bin-sync';\nimport spawnStreaming from 'spawn-streaming';\nimport { createSession, formatArguments } from 'spawn-term';\nimport { objectAssign, stringEndsWith } from './compat.ts';\nimport { storagePath } from './constants.ts';\nimport loadNodeVersionInstall from './lib/loadNodeVersionInstall.ts';\nimport { getPathWithoutNvuBin, resolveSystemBinary } from './lib/resolveSystemBinary.ts';\n\nimport type { Options, UseCallback, UseOptions, UseResult } from './types.ts';\n\nconst isWindows = process.platform === 'win32' || /^(msys|cygwin)$/.test(process.env.OSTYPE);\nconst NODE = isWindows ? 'node.exe' : 'node';\n\n// Parse npm-generated .cmd wrapper to extract the JS script path\nfunction parseNpmCmdWrapper(cmdPath: string): string | null {\n try {\n const content = fs.readFileSync(cmdPath, 'utf8');\n // Match: \"%_prog%\" \"%dp0%\\node_modules\\...\\cli.js\" %*\n // or: \"%_prog%\" \"%dp0%\\path\\to\\script.js\" %*\n const match = content.match(/\"%_prog%\"\\s+\"?%dp0%\\\\([^\"]+)\"?\\s+%\\*/);\n if (match) {\n const relativePath = match[1];\n const cmdDir = path.dirname(cmdPath);\n return path.join(cmdDir, relativePath);\n }\n } catch (_e) {\n // ignore\n }\n return null;\n}\n\n// On Windows, resolve npm bin commands to their JS entry points to bypass .cmd wrappers\n// This fixes issues with nvm-windows where .cmd wrappers use symlinked node.exe directly\nfunction resolveCommand(command: string, args: string[]): { command: string; args: string[] } {\n if (!isWindows) return { command, args };\n\n // Case 1: Command is a .cmd file path\n if (stringEndsWith(command.toLowerCase(), '.cmd')) {\n const scriptPath = parseNpmCmdWrapper(command);\n if (scriptPath) {\n return { command: NODE, args: [scriptPath].concat(args) };\n }\n }\n\n // Case 2: Try to resolve the command as an npm package bin from node_modules\n try {\n const binPath = resolveBin(command);\n return { command: NODE, args: [binPath].concat(args) };\n } catch (_e) {\n // Not an npm package bin, use original command\n }\n\n return { command, args };\n}\n\nexport default function worker(versionExpression: string, command: string, args: string[], options: UseOptions, callback: UseCallback): void {\n // Handle \"system\" as a special version that uses system binaries directly\n if (versionExpression === 'system') {\n runWithSystemBinaries(command, args, options, callback);\n return;\n }\n\n // Load node-version-install lazily\n loadNodeVersionInstall((loadErr, installVersion) => {\n if (loadErr) return callback(loadErr);\n\n resolveVersions(versionExpression, options as VersionOptions, (err?: Error, versions?: string[]) => {\n if (err) return callback(err);\n if (!versions.length) {\n callback(new Error(`No versions found from expression: ${versionExpression}`));\n return;\n }\n\n const installOptions = objectAssign({ storagePath: storagePath }, options) as InstallOptions;\n const streamingOptions = options as Options;\n const results: UseResult[] = [];\n const queue = new Queue(1);\n\n // Create session once for all processes (only if multiple versions)\n const interactive = options.interactive !== false;\n const session = versions.length >= 2 && createSession && !streamingOptions.streaming ? createSession({ header: `${command} ${args.join(' ')}`, showStatusBar: true, interactive }) : null;\n\n versions.forEach((version: string) => {\n queue.defer((cb) => {\n installVersion(version, installOptions, (err, installs) => {\n const install = installs && installs.length === 1 ? installs[0] : null;\n if (err || !install) {\n const error = err || new Error(`Unexpected version results for version ${version}. Install ${JSON.stringify(installs)}`);\n results.push({ install, command, version, error, result: null });\n return cb();\n }\n const spawnOptions = createSpawnOptions(install.installPath, options as SpawnOptions);\n const prefix = install.version;\n\n function next(err?, res?): void {\n if (err && err.message.indexOf('ExperimentalWarning') >= 0) {\n res = err;\n err = null;\n }\n results.push({ install, command, version, error: err, result: res });\n cb();\n }\n\n // On Windows, resolve npm bin commands to bypass .cmd wrappers\n const resolved = resolveCommand(command, args);\n\n if (versions.length < 2) {\n // Show command when running single version (no terminal session, unless silent)\n if (!options.silent) console.log(`$ ${formatArguments([resolved.command].concat(resolved.args)).join(' ')}`);\n return spawn(resolved.command, resolved.args, spawnOptions, next);\n }\n if (session) session.spawn(resolved.command, resolved.args, spawnOptions, { group: prefix, expanded: streamingOptions.expanded }, next);\n else spawnStreaming(resolved.command, resolved.args, spawnOptions, { prefix }, next);\n });\n });\n });\n queue.await((err) => {\n if (session) {\n session.waitAndClose(() => {\n err ? callback(err) : callback(null, results);\n });\n } else {\n err ? callback(err) : callback(null, results);\n }\n });\n });\n });\n}\n\n/**\n * Run command using system binaries (bypassing nvu version management)\n * This handles the \"system\" version specifier\n */\nfunction runWithSystemBinaries(command: string, args: string[], options: UseOptions, callback: UseCallback): void {\n // Find the system binary for the command\n const systemBinary = resolveSystemBinary(command);\n if (!systemBinary) {\n callback(new Error(`System ${command} not found in PATH`));\n return;\n }\n\n // Create spawn options with PATH excluding ~/.nvu/bin\n // This ensures any child processes also use system binaries\n const cleanPath = getPathWithoutNvuBin();\n const spawnOptions: SpawnOptions = objectAssign({}, options as SpawnOptions);\n spawnOptions.env = objectAssign({}, process.env);\n spawnOptions.env.PATH = cleanPath;\n spawnOptions.stdio = options.stdio || 'inherit';\n\n // On Windows, resolve npm bin commands to bypass .cmd wrappers\n const resolved = resolveCommand(command, args);\n\n // For system, use the resolved system binary path\n const finalCommand = resolved.command === command ? systemBinary : resolved.command;\n const finalArgs = resolved.command === command ? args : resolved.args;\n\n if (!options.silent) {\n console.log(`$ ${formatArguments([finalCommand].concat(finalArgs)).join(' ')}`);\n }\n\n spawn(finalCommand, finalArgs, spawnOptions, (err?, res?) => {\n if (err && err.message && err.message.indexOf('ExperimentalWarning') >= 0) {\n res = err;\n err = null;\n }\n\n const result: UseResult = {\n install: null,\n command,\n version: 'system',\n error: err,\n result: res,\n };\n\n callback(err, [result]);\n });\n}\n"],"names":["spawn","fs","resolveVersions","spawnOptions","createSpawnOptions","path","Queue","resolveBin","spawnStreaming","createSession","formatArguments","objectAssign","stringEndsWith","storagePath","loadNodeVersionInstall","getPathWithoutNvuBin","resolveSystemBinary","isWindows","process","platform","test","env","OSTYPE","NODE","parseNpmCmdWrapper","cmdPath","content","readFileSync","match","relativePath","cmdDir","dirname","join","_e","resolveCommand","command","args","toLowerCase","scriptPath","concat","binPath","worker","versionExpression","options","callback","runWithSystemBinaries","loadErr","installVersion","err","versions","length","Error","installOptions","streamingOptions","results","queue","interactive","session","streaming","header","showStatusBar","forEach","version","defer","cb","installs","install","error","JSON","stringify","push","result","installPath","prefix","next","res","message","indexOf","resolved","silent","console","log","group","expanded","await","waitAndClose","systemBinary","cleanPath","PATH","stdio","finalCommand","finalArgs"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node-version/node-version-use/src/worker.ts"],"sourcesContent":["import spawn, { type SpawnOptions } from 'cross-spawn-cb';\nimport fs from 'fs';\nimport resolveVersions, { type VersionOptions } from 'node-resolve-versions';\nimport type { InstallOptions } from 'node-version-install';\nimport { spawnOptions as createSpawnOptions } from 'node-version-utils';\nimport path from 'path';\nimport Queue from 'queue-cb';\nimport resolveBin from 'resolve-bin-sync';\nimport spawnStreaming from 'spawn-streaming';\nimport { createSession, formatArguments } from 'spawn-term';\nimport { objectAssign, stringEndsWith } from './compat.ts';\nimport { storagePath } from './constants.ts';\nimport loadNodeVersionInstall from './lib/loadNodeVersionInstall.ts';\nimport { getPathWithoutNvuBin, resolveSystemBinary } from './lib/resolveSystemBinary.ts';\n\nimport type { Options, UseCallback, UseOptions, UseResult } from './types.ts';\n\nconst isWindows = process.platform === 'win32' || /^(msys|cygwin)$/.test(process.env.OSTYPE);\nconst NODE = isWindows ? 'node.exe' : 'node';\n\n// Parse npm-generated .cmd wrapper to extract the JS script path\nfunction parseNpmCmdWrapper(cmdPath: string): string | null {\n try {\n const content = fs.readFileSync(cmdPath, 'utf8');\n // Match: \"%_prog%\" \"%dp0%\\node_modules\\...\\cli.js\" %*\n // or: \"%_prog%\" \"%dp0%\\path\\to\\script.js\" %*\n const match = content.match(/\"%_prog%\"\\s+\"?%dp0%\\\\([^\"]+)\"?\\s+%\\*/);\n if (match) {\n const relativePath = match[1];\n const cmdDir = path.dirname(cmdPath);\n return path.join(cmdDir, relativePath);\n }\n } catch (_e) {\n // ignore\n }\n return null;\n}\n\n// On Windows, resolve npm bin commands to their JS entry points to bypass .cmd wrappers\n// This fixes issues with nvm-windows where .cmd wrappers use symlinked node.exe directly\nfunction resolveCommand(command: string, args: string[]): { command: string; args: string[] } {\n if (!isWindows) return { command, args };\n\n // Case 1: Command is a .cmd file path\n if (stringEndsWith(command.toLowerCase(), '.cmd')) {\n const scriptPath = parseNpmCmdWrapper(command);\n if (scriptPath) {\n return { command: NODE, args: [scriptPath].concat(args) };\n }\n }\n\n // Case 2: Try to resolve the command as an npm package bin from node_modules\n try {\n const binPath = resolveBin(command);\n return { command: NODE, args: [binPath].concat(args) };\n } catch (_e) {\n // Not an npm package bin, use original command\n }\n\n return { command, args };\n}\n\nexport default function worker(versionExpression: string, command: string, args: string[], options: UseOptions, callback: UseCallback): void {\n // Handle \"system\" as a special version that uses system binaries directly\n if (versionExpression === 'system') {\n runWithSystemBinaries(command, args, options, callback);\n return;\n }\n\n // Load node-version-install lazily\n loadNodeVersionInstall((loadErr, installVersion) => {\n if (loadErr) return callback(loadErr);\n\n resolveVersions(versionExpression, options as VersionOptions, (err?: Error, versions?: string[]) => {\n if (err) return callback(err);\n if (!versions.length) {\n callback(new Error(`No versions found from expression: ${versionExpression}`));\n return;\n }\n\n const installOptions = objectAssign({ storagePath: storagePath }, options) as InstallOptions;\n const streamingOptions = options as Options;\n const results: UseResult[] = [];\n const queue = new Queue(1);\n\n // Create session once for all processes (only if multiple versions)\n const interactive = options.interactive !== false;\n const session = versions.length >= 2 && process.stdout.isTTY && createSession && !streamingOptions.streaming ? createSession({ header: `${command} ${args.join(' ')}`, showStatusBar: true, interactive }) : null;\n\n versions.forEach((version: string) =>\n queue.defer((cb) =>\n installVersion(version, installOptions, (err, installs) => {\n const install = installs && installs.length === 1 ? installs[0] : null;\n if (err || !install) {\n const error = err || new Error(`Unexpected version results for version ${version}. Install ${JSON.stringify(installs)}`);\n results.push({ install, command, version, error, result: null });\n return cb();\n }\n const spawnOptions = createSpawnOptions(install.installPath, options as SpawnOptions);\n const prefix = install.version;\n\n function next(err?, res?): void {\n if (!session && !options.silent) console.log('==============');\n if (err && err.message.indexOf('ExperimentalWarning') >= 0) {\n res = err;\n err = null;\n }\n results.push({ install, command, version, error: err, result: res });\n cb();\n }\n\n // On Windows, resolve npm bin commands to bypass .cmd wrappers\n const resolved = resolveCommand(command, args);\n\n // Show command when running single version (no terminal session, unless silent)\n if (!session && !options.silent) console.log(version);\n if (!session && !options.silent) console.log('--------------');\n if (!session && !options.silent) console.log(`$ ${formatArguments([resolved.command].concat(resolved.args)).join(' ')}`);\n\n if (versions.length < 2) spawn(resolved.command, resolved.args, spawnOptions, next);\n else if (session) session.spawn(resolved.command, resolved.args, spawnOptions, { group: prefix, expanded: streamingOptions.expanded }, next);\n else spawnStreaming(resolved.command, resolved.args, spawnOptions, { prefix: process.stdout.isTTY ? prefix : undefined }, next);\n })\n )\n );\n queue.await((err) => {\n if (session) {\n session.waitAndClose(() => {\n err ? callback(err) : callback(null, results);\n });\n } else {\n err ? callback(err) : callback(null, results);\n }\n });\n });\n });\n}\n\n/**\n * Run command using system binaries (bypassing nvu version management)\n * This handles the \"system\" version specifier\n */\nfunction runWithSystemBinaries(command: string, args: string[], options: UseOptions, callback: UseCallback): void {\n // Find the system binary for the command\n const systemBinary = resolveSystemBinary(command);\n if (!systemBinary) {\n callback(new Error(`System ${command} not found in PATH`));\n return;\n }\n\n // Create spawn options with PATH excluding ~/.nvu/bin\n // This ensures any child processes also use system binaries\n const cleanPath = getPathWithoutNvuBin();\n const spawnOptions: SpawnOptions = objectAssign({}, options as SpawnOptions);\n spawnOptions.env = objectAssign({}, process.env);\n spawnOptions.env.PATH = cleanPath;\n spawnOptions.stdio = options.stdio || 'inherit';\n\n // On Windows, resolve npm bin commands to bypass .cmd wrappers\n const resolved = resolveCommand(command, args);\n\n // For system, use the resolved system binary path\n const finalCommand = resolved.command === command ? systemBinary : resolved.command;\n const finalArgs = resolved.command === command ? args : resolved.args;\n\n if (!options.silent) {\n console.log(`$ ${formatArguments([finalCommand].concat(finalArgs)).join(' ')}`);\n }\n\n spawn(finalCommand, finalArgs, spawnOptions, (err?, res?) => {\n if (err && err.message && err.message.indexOf('ExperimentalWarning') >= 0) {\n res = err;\n err = null;\n }\n\n const result: UseResult = {\n install: null,\n command,\n version: 'system',\n error: err,\n result: res,\n };\n\n callback(err, [result]);\n });\n}\n"],"names":["spawn","fs","resolveVersions","spawnOptions","createSpawnOptions","path","Queue","resolveBin","spawnStreaming","createSession","formatArguments","objectAssign","stringEndsWith","storagePath","loadNodeVersionInstall","getPathWithoutNvuBin","resolveSystemBinary","isWindows","process","platform","test","env","OSTYPE","NODE","parseNpmCmdWrapper","cmdPath","content","readFileSync","match","relativePath","cmdDir","dirname","join","_e","resolveCommand","command","args","toLowerCase","scriptPath","concat","binPath","worker","versionExpression","options","callback","runWithSystemBinaries","loadErr","installVersion","err","versions","length","Error","installOptions","streamingOptions","results","queue","interactive","session","stdout","isTTY","streaming","header","showStatusBar","forEach","version","defer","cb","installs","install","error","JSON","stringify","push","result","installPath","prefix","next","res","silent","console","log","message","indexOf","resolved","group","expanded","undefined","await","waitAndClose","systemBinary","cleanPath","PATH","stdio","finalCommand","finalArgs"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-version-use",
3
- "version": "2.4.4",
3
+ "version": "2.4.6",
4
4
  "description": "Cross-platform solution for using multiple versions of node. Useful for compatibility testing",
5
5
  "keywords": [
6
6
  "node",