#!/usr/bin/env node
'use strict';
const clear = require('clear');
const {readFileSync, writeFileSync} = require('fs');
const {readJson, writeJson} = require('fs-extra');
const {join, relative} = require('path');
const {confirm, execRead, printDiff} = require('../utils');
const theme = require('../theme');
const run = async ({cwd, packages, version, ci}, versionsMap) => {
const nodeModulesPath = join(cwd, 'build/node_modules');
const sourcePackageJSONs = new Map();
for (let i = 0; i < packages.length; i++) {
const packageName = packages[i];
const sourcePackageJSON = await readJson(
join(cwd, 'packages', packageName, 'package.json')
);
sourcePackageJSONs.set(packageName, sourcePackageJSON);
}
const updateDependencies = async (targetPackageJSON, key) => {
const targetDependencies = targetPackageJSON[key];
if (targetDependencies) {
const sourceDependencies = sourcePackageJSONs.get(targetPackageJSON.name)[
key
];
for (let i = 0; i < packages.length; i++) {
const dependencyName = packages[i];
const targetDependency = targetDependencies[dependencyName];
if (targetDependency) {
const sourceDependencyVersion =
sourcePackageJSONs.get(dependencyName).version;
const sourceDependencyConstraint = sourceDependencies[dependencyName];
if (
sourceDependencyVersion ===
sourceDependencyConstraint.replace(/^[\^\~]/, '')
) {
targetDependencies[dependencyName] =
sourceDependencyConstraint.replace(
sourceDependencyVersion,
versionsMap.get(dependencyName)
);
} else {
targetDependencies[dependencyName] = sourceDependencyConstraint;
}
}
}
}
};
for (let i = 0; i < packages.length; i++) {
const packageName = packages[i];
const packageJSONPath = join(nodeModulesPath, packageName, 'package.json');
const packageJSON = await readJson(packageJSONPath);
packageJSON.version = versionsMap.get(packageName);
await updateDependencies(packageJSON, 'dependencies');
await updateDependencies(packageJSON, 'peerDependencies');
await writeJson(packageJSONPath, packageJSON, {spaces: 2});
}
clear();
const printDependencies = (maybeDependency, label) => {
if (maybeDependency) {
for (let dependencyName in maybeDependency) {
if (packages.includes(dependencyName)) {
console.log(
theme`• {package ${dependencyName}} {version ${maybeDependency[dependencyName]}} {dimmed ${label}}`
);
}
}
}
};
for (let i = 0; i < packages.length; i++) {
const packageName = packages[i];
const packageJSONPath = join(nodeModulesPath, packageName, 'package.json');
const packageJSON = await readJson(packageJSONPath);
console.log(
theme`\n{package ${packageName}} {version ${versionsMap.get(
packageName
)}}`
);
printDependencies(packageJSON.dependencies, 'dependency');
printDependencies(packageJSON.peerDependencies, 'peer');
}
if (ci !== true) {
await confirm('Do the versions above look correct?');
}
clear();
if (packages.includes('react')) {
const diffPath = join(cwd, 'build', 'temp.diff');
let diff = '';
let numFilesModified = 0;
for (let i = 0; i < packages.length; i++) {
const packageName = packages[i];
const packagePath = join(nodeModulesPath, packageName);
let files = await execRead(
`find ${packagePath} -name '*.js' -exec echo {} \\;`,
{cwd}
);
files = files.split('\n');
files.forEach(path => {
const newStableVersion = versionsMap.get(packageName);
const beforeContents = readFileSync(path, 'utf8', {cwd});
let afterContents = beforeContents;
while (afterContents.indexOf(version) >= 0) {
afterContents = afterContents.replace(version, newStableVersion);
}
if (beforeContents !== afterContents) {
numFilesModified++;
diff += printDiff(relative(cwd, path), beforeContents, afterContents);
writeFileSync(path, afterContents, {cwd});
}
});
}
writeFileSync(diffPath, diff, {cwd});
console.log(theme.header(`\n${numFilesModified} files have been updated.`));
console.log(
theme`A full diff is available at {path ${relative(cwd, diffPath)}}.`
);
if (ci !== true) {
await confirm('Do the changes above look correct?');
}
} else {
console.log(
theme`Skipping React renderer version update because React is not included in the release.`
);
}
clear();
};
module.exports = run;