Skip to content

Instantly share code, notes, and snippets.

@nicholasadamou
Last active October 1, 2024 20:19
Show Gist options
  • Save nicholasadamou/3344967b896979f52baac282916c3de6 to your computer and use it in GitHub Desktop.
Save nicholasadamou/3344967b896979f52baac282916c3de6 to your computer and use it in GitHub Desktop.
A utility script that determines the appropriate pnpm version based on the Node.js version used in your project. It reads from .nvmrc, package.json, or defaults to the currently installed Node.js version, ensuring compatibility and simplifying dependency management. Optionally, it can also install the recommended pnpm version automatically.
import os
import json
import subprocess
import requests
# Compatibility table for pnpm versions based on Node.js versions (only the major versions)
pnpm_compatibility = {
'14': '6', # PNPM 6 for Node 14
'16': '7', # PNPM 7 for Node 16
'18': '8', # PNPM 8 for Node 18
'20': '9', # PNPM 9 for Node 20
# Extend this mapping as needed
}
# Function to read Node version from .nvmrc file
def get_node_version_from_nvmrc():
nvmrc_path = os.path.join(os.getcwd(), '.nvmrc')
try:
if os.path.exists(nvmrc_path):
with open(nvmrc_path, 'r') as file:
return file.read().strip()
except Exception as e:
print(f"Error reading .nvmrc: {e}")
return None
# Function to read Node version from package.json file
def get_node_version_from_package_json():
package_json_path = os.path.join(os.getcwd(), 'package.json')
try:
if os.path.exists(package_json_path):
with open(package_json_path, 'r') as file:
package_json = json.load(file)
if 'engines' in package_json and 'node' in package_json['engines']:
# Remove any non-numeric characters (like ^, ~, >=) from version
return ''.join(filter(str.isdigit, package_json['engines']['node']))
except Exception as e:
print(f"Error reading package.json: {e}")
return None
# Function to get the currently installed Node.js version
def get_current_node_version():
try:
result = subprocess.run(['node', '-v'], capture_output=True, text=True)
if result.returncode == 0:
return result.stdout.strip().lstrip('v')
except FileNotFoundError:
print("Node.js is not installed or not found in PATH.")
return None
# Function to determine the Node.js version
def get_node_version():
return get_node_version_from_nvmrc() or get_node_version_from_package_json() or get_current_node_version()
# Function to determine appropriate pnpm version
def determine_pnpm_version(node_version):
major_version = node_version.split('.')[0]
target_pnpm_major = pnpm_compatibility.get(major_version)
if not target_pnpm_major:
return 'latest'
# Get the latest compatible pnpm version from the npm registry
try:
response = requests.get('https://registry.npmjs.org/pnpm')
if response.status_code == 200:
data = response.json()
versions = data.get('versions', {})
latest_version = None
for version in versions.keys():
if version.startswith(f'{target_pnpm_major}.'):
latest_version = version # Keep updating to get the latest version in this major line
return latest_version if latest_version else 'latest'
except Exception as e:
print(f"Error fetching pnpm versions: {e}")
return 'latest'
def main():
node_version = get_node_version()
if not node_version:
print("Could not determine Node.js version.")
return
print(f"Node version: {node_version}")
pnpm_version = determine_pnpm_version(node_version)
print(f"Recommended pnpm version: {pnpm_version}")
# Install the required pnpm version
try:
subprocess.run(['npm', 'install', '-g', f'pnpm@{pnpm_version}'], check=True)
except subprocess.CalledProcessError as e:
print(f"Failed to install pnpm version {pnpm_version}: {e}")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment