Skip to content

Instantly share code, notes, and snippets.

@nicholasadamou
Last active October 1, 2024 20:06
Show Gist options
  • Save nicholasadamou/1aa7204bbe658a26adeeed3281bc78cb to your computer and use it in GitHub Desktop.
Save nicholasadamou/1aa7204bbe658a26adeeed3281bc78cb to your computer and use it in GitHub Desktop.
This script, version-pin-and-clean.js, automates the process of pinning and cleaning dependency versions in a package.json file. It reads version information from a pnpm-lock.yaml file and updates both dependencies and devDependencies in package.json to match the versions specified in the lock file, removing any leading version specifiers like ^…
const fs = require('fs');
const path = require('path');
const yaml = require('js-yaml');
console.log('Starting the version pinning and cleaning process...');
// Utility function to determine which package manager is used
const determinePackageManager = () => {
if (fs.existsSync(path.join(__dirname, 'pnpm-lock.yaml'))) {
return 'pnpm';
} else if (fs.existsSync(path.join(__dirname, 'package-lock.json'))) {
return 'npm';
} else if (fs.existsSync(path.join(__dirname, 'yarn.lock'))) {
return 'yarn';
} else if (fs.existsSync(path.join(__dirname, 'bun.lockb'))) {
return 'bun';
}
return null;
};
// Utility function to clean version strings
const cleanVersion = (version) => {
// Remove everything from the first parenthesis till the end of the string
return version.replace(/\(.*$/, '').trim();
};
// Main logic
const packageManager = determinePackageManager();
if (!packageManager) {
console.error('No known package manager lock file found. Aborting...');
process.exit(1);
}
console.log(`Detected package manager: ${packageManager}`);
const packageJsonPath = path.join(__dirname, 'package.json');
let lockFilePath;
try {
// Load the corresponding lock file based on the detected package manager
let lockFile;
switch (packageManager) {
case 'pnpm':
lockFilePath = path.join(__dirname, 'pnpm-lock.yaml');
console.log('Loading pnpm-lock.yaml...');
lockFile = yaml.load(fs.readFileSync(lockFilePath, 'utf8'));
console.log('Successfully loaded pnpm-lock.yaml');
break;
case 'npm':
lockFilePath = path.join(__dirname, 'package-lock.json');
console.log('Loading package-lock.json...');
lockFile = JSON.parse(fs.readFileSync(lockFilePath, 'utf8'));
console.log('Successfully loaded package-lock.json');
break;
case 'yarn':
lockFilePath = path.join(__dirname, 'yarn.lock');
console.log('Loading yarn.lock...');
console.log('Note: Parsing yarn.lock directly is complex. Consider using an appropriate parser.');
process.exit(1);
break;
case 'bun':
lockFilePath = path.join(__dirname, 'bun.lockb');
console.log('Loading bun.lockb...');
console.log('Note: Parsing bun.lockb directly is not yet implemented.');
process.exit(1);
break;
default:
throw new Error('Unsupported package manager');
}
// Load package.json
console.log('Loading package.json...');
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
console.log('Successfully loaded package.json');
// Update dependencies and devDependencies with pinned versions
const updateDependencies = (dependencies, lockDeps, sectionName) => {
if (!dependencies) return;
Object.keys(dependencies).forEach((depName) => {
if (lockDeps[depName]) {
console.log(`Found ${depName} in ${sectionName}, pinning version to ${lockDeps[depName].version || lockDeps[depName]}`);
dependencies[depName] = cleanVersion(lockDeps[depName].version || lockDeps[depName]);
} else {
console.warn(`Warning: ${depName} found in ${sectionName} of package.json but not in ${packageManager} lock file`);
// Clean the version if extra info exists
dependencies[depName] = cleanVersion(dependencies[depName]);
}
});
};
console.log('Updating dependencies...');
if (packageManager === 'pnpm') {
updateDependencies(packageJson.dependencies, lockFile.importers['.'].dependencies, 'dependencies');
updateDependencies(packageJson.devDependencies, lockFile.importers['.'].devDependencies, 'devDependencies');
} else if (packageManager === 'npm') {
updateDependencies(packageJson.dependencies, lockFile.dependencies, 'dependencies');
updateDependencies(packageJson.devDependencies, lockFile.dependencies, 'devDependencies');
}
// Write the updated package.json back to file
console.log('Writing the updated package.json back to file...');
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2), 'utf8');
console.log('Successfully updated package.json with pinned and cleaned versions.');
} catch (e) {
console.error('An error occurred:', e);
}
console.log('Version pinning and cleaning process completed.');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment