UNPKG

@controlplane/cli

Version:

Control Plane Corporation CLI

204 lines 7.89 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.HOMEBREW_FORMULA = exports.PACKAGE_NAME = void 0; exports.detectInstallMethod = detectInstallMethod; exports.detectPackageManager = detectPackageManager; exports.packageManagerUpgradeCommand = packageManagerUpgradeCommand; exports.homebrewUpgradeCommand = homebrewUpgradeCommand; exports.homebrewRefreshCommand = homebrewRefreshCommand; exports.renderCommand = renderCommand; exports.probeInstall = probeInstall; const fs = require("fs"); const io_1 = require("../util/io"); const version_1 = require("../util/version"); Object.defineProperty(exports, "PACKAGE_NAME", { enumerable: true, get: function () { return version_1.PACKAGE_NAME; } }); // ANCHOR - Constants /** Path segments that only appear when Homebrew owns the executable. */ const HOMEBREW_PATH_MARKERS = ['/Cellar/', '/Caskroom/']; /** Path segments that mark a package manager's GLOBAL install root (npm/nvm/n/fnm/volta/asdf/pnpm/yarn, unix and Windows). */ const GLOBAL_INSTALL_MARKERS = [ '/lib/node_modules/', '/appdata/roaming/npm/node_modules/', '/program files/nodejs/node_modules/', '/roaming/nvm/', '/pnpm/global/', '/.config/yarn/global/', '/yarn/data/global/', '/.yarn/', ]; /** The Homebrew formula name for the CLI. */ exports.HOMEBREW_FORMULA = 'cpln'; // SECTION - Functions /** * Infers how the running `cpln` was installed from a set of environment inputs. * * Precedence matters: a Homebrew install is itself a packaged binary, so it must * be checked before the generic packaged-binary case; a source checkout is the * only build without a baked version. * * @param {InstallProbe} probe - The environment inputs describing the running process. * @returns {InstallMethod} The inferred install method. */ function detectInstallMethod(probe) { // A source checkout runs under node and carries no baked version if (!probe.isPackaged && probe.npmVersion === 'dev') { return 'source'; } // Homebrew ships cpln as a packaged binary inside its Cellar/Caskroom if (probe.isPackaged && isHomebrewOwned(probe.execPath, probe.env)) { return 'homebrew'; } // Any other packaged single-binary was downloaded directly if (probe.isPackaged) { return 'binary'; } // A copy in a project's node_modules or the npx cache is a project dependency; // a global upgrade would leave the copy actually in use untouched if (isProjectLocal(probe.scriptPath)) { return 'local'; } // Running under node with a real version means it was installed from a registry return 'npm'; } /** * Determines whether the executable path is owned by Homebrew. * * @param {string} execPath - The real path of the running executable. * @param {NodeJS.ProcessEnv} env - The process environment, consulted for HOMEBREW_* hints. * @returns {boolean} True when the path resolves inside a Homebrew Cellar/Caskroom or prefix. */ function isHomebrewOwned(execPath, env) { // The Cellar/Caskroom segment is the precise, prefix-independent signal if (HOMEBREW_PATH_MARKERS.some((marker) => execPath.includes(marker))) { return true; } // Honor an explicit cellar location exported by a Homebrew shell const cellar = env.HOMEBREW_CELLAR; if (cellar && execPath.startsWith(cellar)) { return true; } return false; } /** * Determines whether the running CLI is a project-local dependency rather than a * global install: in the npx cache, or in a node_modules that is not any package * manager's global root. * * @param {string} scriptPath - The resolved main module path of the running CLI. * @returns {boolean} True when the CLI in use is not a global install. */ function isProjectLocal(scriptPath) { const normalized = normalizePath(scriptPath); // npx runs packages out of its own cache directory if (normalized.includes('/_npx/')) { return true; } if (GLOBAL_INSTALL_MARKERS.some((marker) => normalized.includes(marker))) { return false; } return normalized.includes('/node_modules/'); } /** * Normalizes a path for marker matching: forward slashes, lowercase. * * @param {string} filePath - The path to normalize. * @returns {string} The normalized path. */ function normalizePath(filePath) { return (0, io_1.posixPath)(filePath).toLowerCase(); } /** * Resolves which package manager owns a global npm-family install from the module path. * * @param {string} scriptPath - The resolved main module path of the running CLI. * @returns {PackageManager} The detected package manager, defaulting to npm. */ function detectPackageManager(scriptPath) { const normalized = normalizePath(scriptPath); // pnpm nests global packages under a .pnpm store or a pnpm global directory if (normalized.includes('/.pnpm/') || normalized.includes('/pnpm/global/')) { return 'pnpm'; } // yarn keeps global packages under its own config/data directory // (~/.config/yarn on unix, %LOCALAPPDATA%/Yarn/Data on Windows) if (normalized.includes('/.config/yarn/') || normalized.includes('/.yarn/') || normalized.includes('/yarn/data/global/')) { return 'yarn'; } return 'npm'; } /** * Builds the upgrade command for a given package manager targeting the latest release. * * @param {PackageManager} manager - The package manager to build the command for. * @returns {RunnableCommand} The program and arguments that upgrade the CLI globally. */ function packageManagerUpgradeCommand(manager) { const target = `${version_1.PACKAGE_NAME}@latest`; switch (manager) { case 'pnpm': return { program: 'pnpm', args: ['add', '-g', target] }; case 'yarn': return { program: 'yarn', args: ['global', 'add', target] }; default: return { program: 'npm', args: ['install', '-g', target] }; } } /** * Builds the Homebrew upgrade command for the CLI formula. * * @returns {RunnableCommand} The `brew upgrade cpln` command. */ function homebrewUpgradeCommand() { return { program: 'brew', args: ['upgrade', exports.HOMEBREW_FORMULA] }; } /** * Builds the Homebrew tap-refresh command. Running this before an upgrade prevents * a stale local tap from reporting "already up to date" against an old formula. * * @returns {RunnableCommand} The `brew update` command. */ function homebrewRefreshCommand() { return { program: 'brew', args: ['update'] }; } /** * Renders a runnable command back into a copy-pasteable shell string. * * @param {RunnableCommand} command - The command to render. * @returns {string} The command as a single shell-ready line. */ function renderCommand(command) { return [command.program, ...command.args].join(' '); } /** * Builds an InstallProbe from the live process, resolving symlinks so a Homebrew * bin symlink is seen as its underlying Cellar path. * * @returns {InstallProbe} The environment inputs describing the running process. */ function probeInstall() { var _a, _b; return { execPath: safeRealpath(process.execPath), scriptPath: (_b = (_a = require.main) === null || _a === void 0 ? void 0 : _a.filename) !== null && _b !== void 0 ? _b : '', isPackaged: Boolean(process.pkg) || 'pkg' in process.versions, npmVersion: version_1.About.npm, env: process.env, }; } /** * Resolves a path to its canonical location, falling back to the input when it * cannot be resolved (e.g., the file no longer exists). * * @param {string} filePath - The path to resolve. * @returns {string} The real path, or the original path on failure. */ function safeRealpath(filePath) { try { return fs.realpathSync(filePath); } catch (_a) { return filePath; } } // !SECTION //# sourceMappingURL=install-method.js.map