@mearl/setup
Advanced tools
+6
-22
@@ -5,3 +5,3 @@ import fs from 'node:fs'; | ||
| import { spawn } from 'node:child_process'; | ||
| import { executableNames, findExecutable, isExecutable, prependCommandPath, prependNodePath, resolveSpawnCommand, runCommand, } from './process.js'; | ||
| import { executableNames, findExecutable, isExecutable, prependCommandPath, prependNodePath, resolveSpawnCommand, runCommand, versionManagerExecutableCandidates, } from './process.js'; | ||
| const COMMAND_TIMEOUT_MS = 120_000; | ||
@@ -13,22 +13,2 @@ const MAX_OUTPUT_LENGTH = 1_000_000; | ||
| } | ||
| function versionManagerCandidates(home, executableNames, readdirSync) { | ||
| const roots = [ | ||
| path.join(home, '.nvm', 'versions', 'node'), | ||
| path.join(home, '.fnm', 'node-versions'), | ||
| ]; | ||
| return roots.flatMap(root => { | ||
| try { | ||
| return readdirSync(root, { withFileTypes: true }) | ||
| .filter(entry => entry.isDirectory()) | ||
| .sort((left, right) => right.name.localeCompare(left.name, undefined, { numeric: true })) | ||
| .flatMap(entry => executableNames.flatMap(name => [ | ||
| path.join(root, entry.name, 'bin', name), | ||
| path.join(root, entry.name, 'installation', 'bin', name), | ||
| ])); | ||
| } | ||
| catch { | ||
| return []; | ||
| } | ||
| }); | ||
| } | ||
| export function stripAnsi(value) { | ||
@@ -58,3 +38,7 @@ return value.replace(ANSI_ESCAPE_PATTERN, ''); | ||
| ...names.map(name => path.join(home, 'Library', 'pnpm', name)), | ||
| ...versionManagerCandidates(home, names, readdirSync), | ||
| ...versionManagerExecutableCandidates(home, names, { | ||
| env, | ||
| platform, | ||
| readdirSync, | ||
| }), | ||
| ...(platform === 'win32' | ||
@@ -61,0 +45,0 @@ ? [] |
@@ -0,1 +1,2 @@ | ||
| import fs from 'node:fs'; | ||
| export interface SpawnCommand { | ||
@@ -19,2 +20,8 @@ command: string; | ||
| export declare function executableNames(name: string, platform?: NodeJS.Platform): string[]; | ||
| export interface VersionManagerExecutableCandidateOptions { | ||
| env?: NodeJS.ProcessEnv; | ||
| platform?: NodeJS.Platform; | ||
| readdirSync?: typeof fs.readdirSync; | ||
| } | ||
| export declare function versionManagerExecutableCandidates(home: string, names: string[], options?: VersionManagerExecutableCandidateOptions): string[]; | ||
| export declare function resolveSpawnCommand(executable: string, args: string[], platform?: NodeJS.Platform, commandInterpreter?: string | undefined): SpawnCommand; | ||
@@ -21,0 +28,0 @@ export declare function prependCommandPath(command: string, env?: NodeJS.ProcessEnv): NodeJS.ProcessEnv; |
+31
-0
@@ -17,2 +17,33 @@ import fs from 'node:fs'; | ||
| } | ||
| export function versionManagerExecutableCandidates(home, names, options = {}) { | ||
| const env = options.env ?? process.env; | ||
| const platform = options.platform ?? process.platform; | ||
| const readdirSync = options.readdirSync ?? fs.readdirSync; | ||
| const fnmDefaultRoot = env.XDG_DATA_HOME | ||
| ? path.join(env.XDG_DATA_HOME, 'fnm') | ||
| : platform === 'darwin' | ||
| ? path.join(home, 'Library', 'Application Support', 'fnm') | ||
| : platform === 'win32' && env.APPDATA | ||
| ? path.join(env.APPDATA, 'fnm') | ||
| : path.join(home, '.local', 'share', 'fnm'); | ||
| const roots = [ | ||
| path.join(env.NVM_DIR || path.join(home, '.nvm'), 'versions', 'node'), | ||
| path.join(env.FNM_DIR || fnmDefaultRoot, 'node-versions'), | ||
| path.join(home, '.fnm', 'node-versions'), | ||
| ].filter((root, index, all) => all.indexOf(root) === index); | ||
| return roots.flatMap(root => { | ||
| try { | ||
| return readdirSync(root, { withFileTypes: true }) | ||
| .filter(entry => entry.isDirectory()) | ||
| .sort((left, right) => right.name.localeCompare(left.name, undefined, { numeric: true })) | ||
| .flatMap(entry => names.flatMap(name => [ | ||
| path.join(root, entry.name, 'bin', name), | ||
| path.join(root, entry.name, 'installation', 'bin', name), | ||
| ])); | ||
| } | ||
| catch { | ||
| return []; | ||
| } | ||
| }); | ||
| } | ||
| export function resolveSpawnCommand(executable, args, platform = process.platform, commandInterpreter = process.env.ComSpec) { | ||
@@ -19,0 +50,0 @@ if (platform === 'win32' && /\.(?:cmd|bat)$/i.test(executable)) { |
+1
-1
| { | ||
| "name": "@mearl/setup", | ||
| "version": "2.2.2", | ||
| "version": "2.3.0", | ||
| "description": "One-shot installer, updater, and uninstaller for Mearl environments", | ||
@@ -5,0 +5,0 @@ "type": "module", |
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
52110
2.2%1140
1.97%22
15.79%