Skip to content

Instantly share code, notes, and snippets.

@liady
Last active November 8, 2017 22:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save liady/942add032fd2cb4bf99f20f7602e1c47 to your computer and use it in GitHub Desktop.
Save liady/942add032fd2cb4bf99f20f7602e1c47 to your computer and use it in GitHub Desktop.
Node script for creating a 'bower-lock.json' with exact versions
const fs = require('fs');
const path = require('path');
const resolve = (...args) => path.join(__dirname, ...args);
const lockedVersions = getPackageVersions(resolve('bower_components'));
const newBowerContents = buildNewBowerContents(lockedVersions);
console.log(`Writing to bower-lock.json`);
fs.writeFileSync(resolve('./bower-lock.json'), newBowerContents, 'utf8');
/**
* Reads the current bower.json and replaces every semver with the version from the actual package
* @param {object} lockedVersions The locked versions
* @return {object} The new bower contents.
*/
function buildNewBowerContents(lockedVersions) {
const bowerFileContents = getBowerInfo(resolve('.'));
const areas = ['dependencies', 'devDependencies'];
areas.forEach(area => {
if(!bowerFileContents[area]) {
return;
}
const versionsToChange = {};
console.log();
console.log(`* Locked ${area}:`)
Object.entries(bowerFileContents[area]).forEach(([name, version]) => {
if(isNotDefinite(version) && lockedVersions[name] && lockedVersions[name] != version) {
console.log(`${name}: ${version} -> ${lockedVersions[name]}`)
versionsToChange[name] = lockedVersions[name];
}
});
bowerFileContents[area] = { ...bowerFileContents[area], ...versionsToChange }
})
console.log();
return JSON.stringify(bowerFileContents, null, 2);
}
/**
* Reads the packages in the bower directory and returns an object with the package versions
* @return {Object} The package versions.
*/
function getPackageVersions(bowerComponents) {
try {
const lockedVersions = fs.readdirSync(bowerComponents).reduce((acc, bowerPackage) => {
const { version } = getBowerInfo(path.join(bowerComponents, bowerPackage));
if(version) {
acc[bowerPackage] = version;
}
return acc;
}, {});
return lockedVersions;
} catch (e) {
console.log(e);
return {};
}
}
/**
* Reads and merges bower files in a directory
* @param {string} dir The path to the directory
* @return {object} the merged result of 'bower.json' and '.bower.json'
*/
function getBowerInfo(dir) {
const names = ['bower.json', '.bower.json'];
return names.reduce((acc, name) => {
const fileName = path.join(dir, name);
if(fs.existsSync(fileName)) {
let content;
try {
content = JSON.parse(fs.readFileSync(fileName));
} catch (e) {
console.log(e);
content = {};
}
return {...acc, ...content};
} else {
return acc;
}
}, {});
}
/**
* Determines if the version is not definite (~, ^, *).
* @param {string} version The version
* @return {boolean} True if not definite, False otherwise.
*/
function isNotDefinite(version) {
return version && ['*', '~', '^'].indexOf(version[0]) !== -1;
}
@liady
Copy link
Author

liady commented Nov 8, 2017

Usage

After installing bower packages and verifying everything works, go to the main folder (where bower_components is) and run:

node lockBower.js

It will go through the bower components and copy the exact versions.
A bower-lock.json file will be created, where the semver versions are replaced with the exact ones.
You can replace the original bower.json with it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment